Skip to content
Florian Schuster edited this page Oct 20, 2021 · 10 revisions

the View

  • binds the Controller.state to its components
  • binds interactions to the Controller.dispatch(Action) function

in this example a literal view with a Button and a TextView is implemented. however that does not mean that only a view can have a Controller - there could also be a feature wide or a global Controller that controls the state of the corresponding system or app.

class View(
    private val valueController : Controller<Action, Mutation, State>
) {

    fun onCreate() {
        // bind view actions to Controller.action
       setValueButton.clicks()
            .map { ValueController.Action.SetValue(value = 3) }
            .onEach { valueController.dispatch(it) }
            .launchIn(scope = viewScope)
            
        // bind Controller.state to view
        valueController.state.map { it.value }
            .distinctUntilChanged()
            .map { "$it" }
            .onEach { valueTextView.text = it }
            .launchIn(scope = viewScope)
    }
}

here FlowBinding is used to transform android view events into a Flow

state saving

on Android process death is a common thing. It is possible to get the latest state via Controller.currentState to save it or parts of it and later retrieve it again to set as Controller.initialState.

private val counterValueKey = "value_ key"

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val controller = scope.createController(
        initialState = State(counter = savedInstanceState?.getInt(counterValueKey) ?: 0),
        ...
    )
}

override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    outState.putInt(counterValueKey, controller.state.value.counter)
}
Clone this wiki locally