Android application architecture was toggled from MVC to MVVM (Model-View-ViewModel) to improve the overall application development paradigms.
In the last decade, innovation was in full swing, along with Kotlin for developing cross-platform applications. MVVM was formalised by the Microsoft Co. in the year 2005 and was soon adopted by the web developer community.
Over the last few decades, the issues faced by the software developers are constant, these include writing immaculate codes, possessing a flexible architecture, efficient testing tools, developing interactive UIs, rising up to the expectations of the product management team. Earlier Android codes are written strictly in Java only and were based on the conventional MVC (Model View Controller) architecture.
First, let us discuss the conventional MVC architecture:
Before the advent of MVVM, we used the Model-View-Controller (MVC) and Model-View-Presenter (MVP) design patterns which follow a standard working protocol. Still, the MVC architecture is more popular than the MVP architecture, as it is widely used for documentation. The MVC architecture has three main components, Model, View and Controller and follows a triangular communication pattern.
- The View represents the configuration of the Model
- The Controller manipulates the View input
- The Model to store result formulated by the Controller
The Conventional MVC architecture
Limitations of MVC architecture:
- The disintegrated testing of MVC is difficult due to its communication pattern
- Navigating between the codes is also troublesome
- The content flow is limited is split between the Controller and the Model. However, sometimes View seems to be intervening
Formulation of MVVM
In addition to the standard three components of the MVC and the MVP, MVVM decouples the View from the ViewModel with the help of its fourth component known as Binder. The Binder carries forward the updates from the ViewModel to the View. This allows the development and testing strategies to be in the View to be segregated from the ViewModel. It is very much logical that the GUI should not interfere with the programming logic. Although it is similar to the pre-existing patterns, still it offers the optimal amount of decoupling.
The contemporary MVVM architecture
Image Source: Jay Rambhia
Major components of the MVVM
- View: It is a straight -forward component of the MVVM that contains all the graphical user interface components. While working with Android studio and activity or fragment is usually referred to as the View. It relays the input to the ViewModel and displays the output received from the ViewModel.
- Model: It is another elementary component that is completely isolated from the activities of the other components and independent. It preserves the configuration of the system so that the ViewModel may run queries on it. It is typically based on the repository pattern. Especially for Android, Google launched the Room Persistence library within Jetpack to carry out the Create-Read-Update-Delete (CRUD) operations on the Model repositories.
- ViewModel: It is the central component of the MVVM architectural pattern. It consists of the logical framework of the application. The ViewModel needs to capture the data present in the Model so that the View can display it. The ViewModel also transforms the input events into data form so that the Model can sustain it. If you encounter any error, go through the ViewModel first. The ViewModel gets initialised with a repository so that it can establish a communication with the Model. It contains several functions that provide the output. For example -generateReport().
- The Binder: It is used to establish the connection between the View and ViewModel. The Binder is included with the help of third-party libraries; the developer can easily implement that into their source code with the help of plugins.
The components of MVVM architecture
Image Source: raywenderlich
MVVM and LiveData: LiveData is the recently introduced class and is popularly known as an observable data holder class. This enables us to automatically detect the changes in the activity lifecycle without tracking each activity explicitly. This allows the lifecycle object producer to be completely independent of the live data object consumer. LiveData considers the current state of each and every activity and preserves the LiveData objects accordingly. In contrast to a library like Rx or Agera, where we have to track the activity lifecycles and manage object allocation and deallocation explicitly. As LiveData is already aware of the activity life cycle, it will never invoke an activity which is not in the active state or has been destroyed using the onDestroy() method.
For working with Live Data, you need to include the following permission in AndroidManifest.xml
Advantages of LiveData
- No abrupt memory loss: Observers are restricted to the lifecycle of the objects and cannot destroy any object if its lifecycle is not completed. The objects are automatically destroyed and cleared from the stack after the completion of their lifecycle.
- Significant reduction in activity crashes: Since the view objects will not get destroyed or added to the back stack abruptly, the View won’t get altered until the activity is completed. In contrast to a regular observable, Live Data is aware of the lifecycle of the other components of the application, including the activities, fragments, adaptors and other UI components. This ensures that LiveData will only trigger an activity that is currently in the active state; this reduces app crashes significantly.
- No need for writing redundant code for lifecycle management: As LiveData automatically detects the lifecycle amendments in the user-interface, you don’t need to explicitly finish or invoke any activity.
- Auto-adaptation: If the configuration of user-interface is updated while the user is rotating the device, he receives the latest live statistics.
Each observer is notified about the state change of activity/fragment
Image Source: codelabs.developers.google
MVVM and Dagger
Dependency injection is complicated to understand, especially for beginners; you can be efficient in injecting dependencies only after attaining a certain level of experience. But this doesn’t imply that our applications can work efficiently without these dependencies. External dependencies are very crucial for memory optimisation and scalability. For this, we can rely on the DI frameworks like Spring, Guice and Dagger.
Dagger is a DI framework, introduced by Google; it is wide-spread in the Android developers’ community as it generates a dependency hierarchy at the compile time.
Advantages of Dagger:
- Reduces boilerplate code: It allows us to inherit pre-existing helper classes for implementing DIs in android applications.
- Improvement is going on: Google is working on adding more features to the Dagger and is still maintain the pre-existing framework.
- Availability of migration guide: Google has launched a migration guide for its latest dagger-android library.
- Dagger Android version: You can toggle between Dagger or dagger-android while doing projects, but you must include at least one of them for DI implementation.
Image Source: codelabs.developers.google
MVVM and Data binding
Data Binding is a powerful tool that saves a lot of development time when you are updating any data and linking it with the UI. Most of us are familiar with the elementary findViewById() method in Java and its alternate Kotlin Android Extensions, but some of the corner cases are skipped while working with them. With the use of Data Binding libraries, you can closely relate views in your XML code along with the features of your binding object.
Advantages of Data Binding:
- Synchronisation: It continuously syncs the database alterations with the UI components, so that the consumer is always updated. It also synchronises the ViewModel along with View.
- Constant code location: The View components remain in the layout XML file and data binding generates intermediate codes from them.
- Two Way Data Binding: This allows us to establish two-way communication between the XML layout and the database objects. It to regularly updates the changes made in the database to the UI. You can add a BindingAdapter so that the ViewModel can provide data to the layout as well as observe changes.
We can enable data binding in our Android project by adding the following code snippet in the build.gradle file
enabled = true
MVVM and Rx Java
Reactive Extensions (Rx) are a collection of methods and interfaces that help in saving the overall development time of a mobile application. It appears to be complicated in the beginning but eventually helps you in writing distinct codes with lesser effort. With the use of Reactive extensions in Java, the developers can manipulate the actions that are triggered by system events. It allows us to implement functional transformations over streams of events and eliminate the need for callbacks and global state management.
Advantages of Rx Java:
- It allows us to schedule async operations: If you have to invoke one API from another API; you can simply invoke the second in the callback of the first one. RxJava eliminates the need for creating layered callbacks. That’s the main reason behind Netflix adopting RxJava in 2014.
- Extendable: We can customise the pre-existing libraries according to our requirement.
- Inbuilt conversion support: Operators in RxJava can covert pre-existing data types by processing, filtering and expanding data streams.
Frequently Asked Question
How many components are there in MVC architecture?
There are three main components in MVC architecture. They are as follows:
What is difference between controller and model?
The Controller manipulates the View input. Whereas, the Model to store result formulated by the Controller.
What is the use of RX?
Reactive Extensions (Rx) are a collection of methods and interfaces that help in saving the overall development time of a mobile application.