Implement Redux with Android Observer/Livedata/Coroutine/Kotlin

Viewed 1191

Consider the Android app architecture that is recommended by Google: https://developer.android.com/jetpack/docs/guide
This architecture is based on ViewModels and Observables, therefore I would categorize it as "Model-View-ViewModel" (MVVM) architecture.

This is quite different to React-Redux. Whereas the Android architecture encourages bi-directional dataflows between Views and ViewModels, Redux enforces a uni-directional dataflow in a circle. Moreover, the Android architecture keeps state in several ViewModels, whereas Redux enforces a centralized store.

Now my question is how to implement Redux with native Android libraries. My first attempt would be:

  • Implement a centralized store as a Kotlin Singleton object.
  • The store provides a sendAction-method that takes an action, puts it in a queue and then returns quickly.
  • Actions are pure Kotlin data classes because they should not contain any logic.
  • Within the store, implement a Kotlin-Coroutine that picks up actions from the queue and dispatches them with a huge switch-statement.
  • Use a Room-database + some ephemeral state as a model. In particular, the ephemeral state controls which Fragment/Dialog is shown at any given time.
  • Ensure that the state is only mutated by the Coroutine.
  • Use observable livedata (androidx.lifecycle.LiveData) to re-render the UI whenever the Room-database or the ephemeral state changes.
  • Since observables are not enough to control an Android UI, I would also need a function that compares the current fragment/activity with the expected state, and e.g. trigger a FragmentManager transaction if a deviation is detected.

However, a few points are not clear:

  • How to keep activity/fragments in sync with the global state? Perhaps I would use a single activity and replace fragments as needed, depending on the current state of the store.

  • How can I implement both async + sequential action dispatching? Perhaps I would implement a single Kotlin-Coroutine that picks up incoming actions from the queue and dispatches them straight on the UI thread.

  • How can we ensure that the entire UI is re-rendered before new actions are dispatched? Perhaps I would stall the dispatching coroutine until there are no more other runnables in the queue of the UI thread?

1 Answers

You are right to say there are some limitations with MVVM.

Redux-style architecture tends to get called 'MVI' or 'Unidirectional' in Android.

There are some attempts at implementing this architecture in Android already that you can take a look at to help answer your questions:

MvRx

Mosby

In addition, this summary page has a list of articles/libraries describing the approach.

Related