Over the past years, app architecture has evolved. From god activities to MVP to MVVM which became popular after Google announced Android architecture components to MVI. the latest in the MV* band.
Jetpack compose, the modern UI toolkit for Android introduces a new way of writing your App UI. It is declarative. Hence, compose works fluently with unidirectional data flow architectural patterns.
In this session, we’ll see how the common architectural patterns work with Jetpack compose paradigm. We’ll go through the Model as the single source of truth. We’ll also look at handling SingleLiveEvents and app navigation using MVI pattern, and the benefits of unidirectional data flow. In the end, we’ll have fewer UI - related bugs in our Android apps.
Android Engineer @ Kyosk Digital
Android Author @ kodeco.com
@B__Kinya | Beatrice Kinya
Android, Kotlin, Jetpack
How it Started.
- Performance issues.
- Lifecycle issues
- Memory leaks
- Out of Memory issues
Model - View - Presenter
- Model - View - Presenter
- Model is just data.
- Presenter fetches data from the model, and manages state of the view.
- It takes action based on user input in the View.
- It calls methods on the View to notify it of state changes.
- View receives method calls from the Presenter to be notiﬁed of changes to update
- Presenters have a reference to the view. The view ia usually an activity or fragment
injected into the presenter as an interface.
- The presenter call functions on the interface to update the UI.
- Composable functions do not have a return value. Hence, no view references to
pass to our presenter.
- Making MVP less ideal for Jetpack compose projects.
Model - View - ViewModel
- Became popular when Google announced AAC: ViewModel, LiveData etc.
- ViewModel is the link between the View and Model.
- ViewModel stores and manages UI related data in a lifecycle conscious manner.
- Model is data mapped into observable ﬁelds like LiveData, or StateFlow.
- When there are changes in the model, the UI observes the changes and
recomposes itself based on the new data.
- Instead of updating the view imperatively like in MVP, MVVM uses observable data
types making it a unidirectional Data Flow architectural pattern.
- Downside: multiple objects for diﬀerent UI states.
Model - View - Intent
- In MVVM, model is just data e.g. A list of movies
- In MVI, model represents state.
- It tells the view what to display E.g. Loading, Data, Error.
- When the model changes, the view gets notiﬁed and recomposes itself using the
- An action that changes state e.g. user fetching favourite movies from an Api
- MVI pattern uses redux style to create new state.
- There are three components:
- State - state holder
- Action - Command to change state
- Reducer - a pure function that takes the previous state and action and creates
a new state
- Reduce function directly in the ViewModel
- Separate the reducer from ViewModel
- Reducer will be responsible for holding and processing state
- ViewModel will be responsible for presentation layer business-logic, and
transforming events from the UI layer into Intentions passed to the Reducer.
- UI i.e. a composable function.
- It listens and responds to state changes.
- Publishes stream of events as they happen to the ViewModel.
- Optional feature.
- It saves all states during a session.
- You can do with it as you want: log to crashlytics, display in a debug menu or a
screen where you can check all the steps made previously.
- Note: Consider not to implement this by default. You’ll have chatty logs. Just use it
for debugging purposes
Handling Conﬁguration changes
- The UI will display the most recent state.
- However, remember to save state object.
- ViewModel to handle conﬁguration changes like screen rotation
- ViewModel saved state module to handle process death
- Any other state saving mechanism
Single Live Events
- E.g. Showing a snackbar message.
- During conﬁguration changes, the app will use the latest state.
- It’ll show the snackbar again, which is not so good.
- There are several ways to handle single live events
- Sending ViewModel events to the UI - Google recommendation
- Using Kotlin Channel
Sample project: https://github.com/BKinya/Calculator-App
- Making navigation be part of our state
- State should hold data the app should show on a screen
- Handled as a side eﬀect.
- But side eﬀects are related to API calls, database access, remote logging
- Call navigation directly from the UI. My preference.
- Improved state management.
- The “planning” eﬀect.
- Unidirectional/Cyclic Data Flow.
- Immutability, hence single source of truth.
- Debuggability with time machine.
- Lot’s of boilerplate code.
- Each view will at least have a model, intent and a reducer function.
- For large projects, this is a non- trivial organisation problem.
- Use Android studio template support
- Implement base interfaces
- Sample project: https://github.com/BKinya/Movies-App
- Reactive Apps using MVI: http://hannesdorfmann.com/android/mosby3-mvi-1/
- MvI, a new member of MV band:
- MVI - the good, bad and ugly:
- State and Jetpack compose: https://developer.android.com/jetpack/compose/state
- State holders and state production in the UI layer.