First add the ReKotlin dependency to your build script.
dependencies {
implementation 'io.github.rakutentech.rekotlin:rekotlin:2.1.0'
}
For a very simple app, that maintains a counter that can be increased and decreased, you can define the app state as following:
typealias AppState = Int?
To change the state you define actions, one for increasing and one for decreasing the state. For the simple actions in this example we can define empty data classes that conform to action:
data class IncrementAction(val amount: Int = 1): Action
data class DecrementAction(val amount: Int = 1): Action
The reducer needs to handle actions to create the changed state:
fun reducer(action: Action, oldState: AppState?): AppState {
// if no state has been provided, create the default state
val state = oldState ?: 0
return when(action){
is IncrementAction -> state + action.amount
is DecrementAction -> state - action.amount
}
}
Reducers must be pure functions without side effects.
To maintain our application state we need to wire it all up in a store:
val store = store(
reducer = ::reducer,
state = 7 // the initial state is optional
)
// or more concisely
val store = store(::reducer)
Lastly, your want to observe the state in order to render it to the user.
class CounterViewComponent(
private val label: TextView,
private val button: Button,
private val store: Store<AppState>
) : Subscriber<AppState> {
init {
store.subscribe(this) // (1)
// you will need to call store.unsubscribe to stop being notified of state changes,
// for example in an onPause or onDestroy lifecycle callback.
button.setOnClickListener { store.dispach(IncrementAction()) } // (2)
}
override fun newState(state: AppState) { // (3)
label.text = "We are counting.... so far we have: ${state}"
}
}
Let’s look in more detail at the numbered lines:
CounterViewComponent
to receive state updates from now on. At subscribe time it will be called once to receive the current state.CounterViewComponent
once the reducers have determined the new state!Here you go, your first fully functional unidirectional data flow! 🎉