在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称(OpenSource Name):GeoThings/ReKotlin开源软件地址(OpenSource Url):https://github.com/GeoThings/ReKotlin开源编程语言(OpenSource Language):Kotlin 100.0%开源软件介绍(OpenSource Introduction):ReKotlin (preview)https://github.com/ReKotlin/ReKotlinHas been moved toPort of ReSwift to Kotlin, which corresponds to ReSwift/4.0.0 IntroductionReKotlin is a Redux-like implementation of the unidirectional data flow architecture in Kotlin. ReKotlin helps you to separate three important concerns of your app's components:
The ReKotlin library is tiny - allowing users to dive into the code, understand every single line and hopefully contribute. About ReKotlinReKotlin relies on a few principles:
For a very simple app, that maintains a counter that can be increased and decreased, you can define the app state as following: data class AppState (
val counter: Int = 0
): StateType You would also define two actions, one for increasing and one for decreasing the counter. For the simple actions in this example we can define empty data classes that conform to action: data class CounterActionIncrease(val unit: Unit = Unit): Action
data class CounterActionDecrease(val unit: Unit = Unit): Action Your reducer needs to respond to these different action types, that can be done by switching over the type of action: fun counterReducer(action: Action, state: AppState?): AppState {
// if no state has been provided, create the default state
var state = state ?: AppState()
when(action){
is CounterActionIncrease -> {
state = state.copy(counter = state.counter + 1)
}
is CounterActionDecrease -> {
state = state.copy(counter = state.counter - 1)
}
}
return state
} In order to have a predictable app state, it is important that the reducer is always free of side effects, it receives the current app state and an action and returns the new app state. To maintain our state and delegate the actions to the reducers, we need a store. Let's call it val mainStore = Store(
reducer = ::counterReducer,
state = null
)
class MainActivity : AppCompatActivity(){
//...
} Lastly, your view layer, in this case an activity, needs to tie into this system by subscribing to store updates and emitting actions whenever the app state needs to be changed: class MainActivity : AppCompatActivity(), StoreSubscriber<AppState> {
private val counterLabel: TextView by lazy {
this.findViewById(R.id.counter_label) as TextView
}
private val buttonUp: Button by lazy {
this.findViewById(R.id.button) as Button
}
private val buttonDown: Button by lazy {
this.findViewById(R.id.button2) as Button
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// when either button is tapped, an action is dispatched to the store
// in order to update the application state
this.buttonUp.setOnClickListener {
mainStore.dispatch(CounterActionIncrease())
}
this.buttonDown.setOnClickListener {
mainStore.dispatch(CounterActionDecrease())
}
// subscribe to state changes
mainStore.subscribe(this)
}
override fun newState(state: AppState) {
// when the state changes, the UI is updated to reflect the current state
this.counterLabel.text = "${state.counter}"
}
} The Button taps result in dispatched actions that will be handled by the store and its reducers, resulting in a new app state. This is a very basic example that only shows a subset of ReKotlin's features, read the Getting Started Guide (not ported yet) to see how you can build entire apps with this architecture. For a complete implementation of this example see the ReKotlin-CounterExample project. You can also watch this talk on the motivation behind the original ReSwift. Why ReKotlin?Model-View-Controller (MVC) is not a holistic application architecture. Typical apps defer a lot of complexity to controllers since MVC doesn't offer other solutions for state management, one of the most complex issues in app development. Apps built upon MVC often end up with a lot of complexity around state management and propagation. We need to use callbacks, delegations, Key-Value-Observation and notifications to pass information around in our apps and to ensure that all the relevant views have the latest state. This approach involves a lot of manual steps and is thus error prone and doesn't scale well in complex code bases. It also leads to code that is difficult to understand at a glance, since dependencies can be hidden deep inside of view controllers. Lastly, you mostly end up with inconsistent code, where each developer uses the state propagation procedure they personally prefer. You can circumvent this issue by style guides and code reviews but you cannot automatically verify the adherence to these guidelines. ReKotlin attempts to solve these problem by placing strong constraints on the way applications can be written. This reduces the room for programmer error and leads to applications that can be easily understood - by inspecting the application state data structure, the actions and the reducers. This architecture provides further benefits beyond improving your code base:
The ReKotlin tooling is still in a very early stage, but aforementioned prospects excite us and hopefully others in the community as well! Getting Started GuideGetting started guide has not yet been ported. In the meantime, please refer to original ReSwift's: Getting Started Guide that describes the core components of apps built with ReSwift. To get an understanding of the core principles we recommend reading the brilliant redux documentation. InstallationWe are still in preview here, so the package is not yet available at maven central repository. Instead please use our development repository: // build.gradle
repositories {
maven {
url 'https://rekotlin.s3-ap-southeast-1.amazonaws.com/snapshots'
}
}
dependencies {
compile 'tw.geothings.rekotlin:rekotlin:0.1.0-SNAPSHOT'
}
Differences with ReSwiftDereferencing subscribers will not result in subscription removedIn ReSwift when you dereference the subscriber or it goes out of the scope, you won't receive new state updates. var subscriber: TestSubscriber? = TestSubscriber()
store.subscribe(subscriber!)
subscriber = nil However in ReKotlin you need make sure you have unsubscribed explicitly. val subscriber = TestSubscriber()
store.subscribe(subscriber)
store.unsubscribe(subscriber) Equatability and skipRepeatsWhen subscribing without substate selection like public struct State: StateType {
public let mapState: MapState
public let appState: AppState
}
extension State: Equatable {
public static func ==(lhs: State, rhs: State) -> Bool {
//...
}
}
However in Kotlin(JVM) every object implements Please note, if you implement your states/substates with data classes, Kotlin compiler will automatically derive non-shallow If you want to opt-out of this behaviour please set val store = Store(
reducer::handleAction,
state,
automaticallySkipRepeats = false) Credits
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论