Our mobile team develops CashNetUSA mobile applications both for iOS and Android. This blog is written to discuss specifically our Android Installment app, which was developed last year and released around March 2019. During our initial development, we used the MVP (Model-View-Presenter) pattern. It works great for various reasons, but also it has its own limitations. So we start exploring a new architecture, and we come up with an MVVM (Model-View-ViewModel) pattern.
Let’s start with some basic Android terminology for those who do not know Android.
Android Activity and Fragments
“Activity,” in a simple case, represents a screen in Android. However, the Activity can contain multiple ‘small views’, which we call fragments. In other words, an Activity might contain multiple fragments.
This picture below shows an example of an activity with 3 fragments.
MVP (Model View Presenter)
This picture below depicts what is MVP:
Model: This is a simple data model.
e.g A “loan object” which has loan id, due date, the amount due, etc.
Presenter: It performs some business rules and tells the View on what to display. It is a pure Java / Kotlin class and does not have the Android SDK code.
View: This is basically either the Activity or the Fragment implementation. It uses the Android SDK or libraries.
The picture below depicts how the Android MVP pattern gets implemented.
Each fragment and activities have a presenter and a view.
What does the handshake mean? It means:
- The View – Presenter relationship is 1 vs 1.
- The View – Presenter relationship is tightly coupled.
- Code separation between UI code and business logic code
- Easy to test
- See the handshake? It means that it is tightly coupled. So if we want to change the UI, we need to change the presenter or even worse, create a new presenter.
- There is no single place in the code to put the business logic. Each fragment presenters can have their own logic.
Scenario 1 – MVP Display Data to Screen
This is an example of how we fetch data from the backend and update the screen. This illustrates how the data flows.
In summary, this is the sequence:
- The main activity presenter is responsible to get the borrower.
- The main activity then passes the borrower to the fragments.
- Each fragment has its own ‘business logic’, for example, in this case, fragment 1 needs to get the loan balance while fragment 2 needs to get the payment date.
Notice that each view (Main Activity, Fragment 1, and Fragment 2) has a little bit API requests here and there.
Moving all the API requests from fragments to the main activity might help a little bit, but still, we can’t reuse it for other activities. See the picture below.
Scenario 2 – MVP Update data to multiple screens
How about if fragment 3 is updating the data, and we want to update fragment 1 and fragment 2?
The activity needs to listen to any update from the fragment, then distribute the updated data to other fragments. In short, these are the steps:
- The activity needs to listen to any update from Fragment 3
- Fragment 1 and Fragment 2 needs to listen to any update from Activity
- When the update button is clicked, fragment 3 tells its listener that they have updated the name.
- When activity receives the updated data, then it needs to pass this data to any fragments who listen to this event.
Notice that there are so many listeners that we need to implement to pass the data between screens.
Remember the handshake from above? This is what would happen.
So how does MVVM help the development?
MVVM (Model-View-ViewModel) main items are:
- The View -> The View observes any data changes from the ViewModel.
- The ViewModel -> Responsible to ‘broadcast’ data to the Views
- The Model -> The data model, i.e: Loan model that has loan id, outstanding balance, etc.
MVVM is also known as the “Data Binding” pattern, or “Observer” pattern.
The big difference from MVP pattern is that in the MVP pattern, the Presenter is telling the View directly what to display, and the Presenter and the View relationship is 1 to 1.
While in the MVVM pattern, the ViewModel does not need to hold a reference to the View anymore and the ViewModel has no information about the View. Therefore, the View – ViewModel relationship is loosely coupled.
In short, ViewModel is responsible to broadcast the live data. The View(s) needs to observe for any data updates from the ViewModel.
The ViewModel also serves as 1 place in the code where we can do business logic without worrying about what the UI is doing.
Distributing data across screens also way simpler because each screen has listened to any update on the data already, and we do not need to pass the data around.
MVVM allows us to provide business logic in one place while leveraging the advantages of data bindings. It allows us to minimize business logic from the views and allows us to refactor the views faster.