I'm trying to implement the MVP pattern into my project following the android blueprints guide. Currently, I am holding the User (entity data) within my Presenter, which I really dislike, because, on every configuration change, the presenter fetches the user from the database.
My first question is:
I am also aware of android architecture components, ViewModel in particular, however, I would like to keep the MVP pattern instead of MVVM.
My second question is:
I've been stuck on this problem for quite a while and would love to finally get through it.
Cheers
What is MVP? The MVP pattern allows separating the presentation layer from the logic so that everything about how the UI works is agnostic from how we represent it on screen. Ideally, the MVP pattern would achieve that the same logic might have completely different and interchangeable views.
MVP (Model — View — Presenter) comes into the picture as an alternative to the traditional MVC (Model — View — Controller) architecture pattern. Using MVC as the software architecture, developers end up with the following difficulties: Most of the core business logic resides in Controller.
MVVM is better than MVC/MVP because of its unidirectional data and dependency flow. Dependency is one way, thus it is a lot easier to decouple it when we need to. It is also easier for testing. All my projects(written in Kotlin for Android app) are based on MVVM.
Why use Data binding with Mvp? Combining Databinding along wih MVP pattern can result in a very clean structure and maintainable project. Databinding saves u a lot of stress and uneccesary long lines of code. Your UI is updated eaily and gone are those days where you need "findViewById" and onclick listeners and so on.
Should I keep my data in the Repository or should I keep it within the presenter and persist it there somehow?
You have an interesting question which once I had as well when I started working with MVP. Here is my 2 cents:
There has been continuing discussions on the two options that you mentioned. I personally prefer the repository pattern. It is much cleaner IMO and the dealing with cases like screen rotation when a request is already in flight etc becomes easier with it. Also every time the device rotates, you need not fetch from the db. If you think that's expensive, maybe you can create a level of cache before db. There is a very interesting and detailed article: Presenters are not for persisting by Mike Nakhimovich, who during his time as Android Developer at New York Times worked on a library called Store which helps achieve the same. From the article:
I'd propose using data stores which abstract away data loading. Rather than the presenter needing to cache the data, we can leverage the Repository pattern and create Data Providers/Stores that can get data from the network and cache it for when we need it. For one thing, this approach makes it easier to persist your data. Another advantage is that we have a single source of truth for our data. Finally, we can eliminate things like Interactors and just have your Presenter subscribe to your Stores whenever they need something for a view.
Hope this helps a bit.
The Repository should only act as your gate for accessing data from different data sources.
For example
If you can fetch user data both from an API and and from disk (cached data), you isolate the logic of the decision of choosing which data source to get from in the Repository class. The presenter should know nothing about this. The presenter only asks for the user data
That being said
The presenter needs to hold a reference to the data it's querying (i.e. UserModel), the repo only retrieves the data from whatever data source and that's it. Same applies for any data-related operations (save, delete, update, retrieve, etc...). So if you need to hold an application scope reference to your data object, create a separate class let's say named InMemoryStore
and mark it as application scope and keep the references in it. Use the Repository pattern to query the data from it.
Also important to note
Each layer should hold a different form of the data. The model used in the view layer (i.e. recycler view) should only hold the data needed for the view, nothing more nothing less. Same goes for the presenter and the model layer (usually the model layer holds the most info about the model)
This means that you will need a mapper class for each model class to convert from one form to the other. You can refer to this example for better understanding
Lastly
Since i use RxJava i didn't feel the need to use LiveData so i'm not aware enough of this topic.
You can check this full example for how to apply MVP with RxJava and Dagger
I hope this was helpful and clear :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With