Skip to content
Florian Schuster edited this page Feb 29, 2020 · 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 and then save it and later retrieve it again:

private val counterValueKey = "value_ key"

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

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

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