Android App Architecture with Koin & MVPVM
I did already talk about different architectures in Android, you can check them HERE.
What I want to share with you is the latest architecture that we use inside my latest project. We call it the Vertical Architecture. So how does it look like.
We have the ordinary layers like we have in other architectures like:
– API/DB sources
Here is a sample diagram how this thing looks like
Short explanation how things work
- All of the communication happens using RxJava
- Activity / Fragment holds reference to both ViewModel & Presenter
- Activity / Fragment can communicate with the presenter in 2 ways
- It calls presenter methods directly like presenter.createSomething()
- It listens for events that come from the presenter. Usually, these events have “Action” in their name. These events are represented by an Observable, that is actually a hidden Subject. So whenever the Presenter wants to tell the View to do something, he uses an “GoToNextScreenAction” that is emitted through the Subject.
- Each Activity/Fragment exposes a uiEvents variable which is an Observable that emits stuff like click events, touch events etc. Presenter can listen for these events by accepting them in the constructor. We use Koin to pass the uiEvents observable to the presenter.
- ViewModel has a list of Observable fields that are used in the UI like texts, integers etc. But if you want to tell the Activity / Fragment to go to another screen, you just emit an action, you don’t set a property in the ViewModel.
- Presenter & ViewModel share the same scope so whenever the presenter modifies the ViewModel, the ViewModel change is reflected inside the UI. It means that we have only one Presenter & ViewModel per scope (activity/fragment).
- ViewModels also contain the Observable<List<Data>>. Meaning that you need to have an adapter that works with DataBinding. You can make this adapter have a uiEvents variable and then expose adapter clicks up to the presenter.
- All of the RxJava subscriptions are managed with the Lifecycle observable class
Why does this architecture work?
Well, it is quite simple.
- You handle UI events in the presenter. All click/touch events are delivered to the presenter by the uiEvents observable. This way it makes it easier to test the UI logic by writing unit tests. You just emits some events.
- Presenter and View are decoupled. You don’t need to have a reference to your view. You emit an “action” and if the view has subscribed – it will receive it. No need for contracts. This is actually a double edge sword. It makes it hard to see what events the View can handle but you can easily check that by reviewing the handlePresenterActions function.
- View has a ViewModel so the presenter doesn’t need to pass the data down the View. You can still use the DataBinding framework and benefit from it. You can easily test views by mocking ViewModels
- Using Koin makes everything really simple. Just check the MainModule class.
Show me the code
An example can be found on my Github HERE.