Why MVVM and How to execute MVVM combined with Data Binding and LiveData in Four Simple Steps

Like many other technology components, the design architectures to create Android applications also kept advancing with time to cope with the increasing complexities of modern applications.

Recently, Model View ViewModel (MVVM) has emerged as one of the most efficient architectural patterns. Even in the Google I/O 2017 event, Google also recommended it for creation of Android applications.

In this blog, I will share how to execute MVVM combined with Data Binding and LiveData for an Android app with the example of a Login Module. Before we start, let us have a brief comparison among MVC, MVP and MVVM.

Traditionally utilized for desktop GUIs, over the time MVC populated among developer community for the development of web and mobile apps as well. Its successors MVP and MVVM could overcome its concerns and furnished the developers with a modular and flexible architectural pattern.

 

MVCMVPMVVM
Model View ControllerModel View PresenterModel View ViewModel
Model: Data, State and Business LogicModel: Same as MVCModel: Same as MVC
View:

In MVC, View is the kind of Representation of Model

During user interactions, it renders UI and communicates to Controller

It does not have any knowledge about Model or State

View:

In MVP, Activity or Fragment is considered as a part of View.

View:

In MVVM, the View binds observable variables and actions with reasonable resilience

Controller:

Controller is meant for binding the application together

When View communicates with Controller, Controller takes the call about how to interact with the Model in the suitable manner

If data gets updated in Model, Controller decide to change the state of View accordingly

Presenter:

The Presenter is a kind of controller that is not tied with the View

It acts as an interface

ViewModel:

The ViewModel wraps the Model as well as prepare observable data

It proffers hooks to View so that the View can pass desired events to the Model

Concerns with MVCConcerns with MVPConcerns with MVVM
Testability – Model is easy to test and View has nothing to be tested. However, unit testing becomes inconvenient in Controller as it is tightly tied to Android API

Maintenance – Over the time, Controller becomes loaded with the code being transferred to it

Flexibility and Modularity – Due to its tight coupling with View, Flexibility becomes one of the biggest concerns for Controller. If you we need to make any change in View layer, we have to make similar change in controller as well.

Maintenance– Maintenance becomes difficult with MVP as well because similar to Controller, Presenter also gets loaded with code being transferred to itMaintenance – In MVVM, View can tie variables and expressions. Hence, eventually, lot of code can be added to XML.

However, it is possible to overcome this concern by getting values directly from the ViewModel instead of binding expressions with View

Thus, if used smartly, we can say that MVVM has no such concerns.

Advantages of using MVVM with Data Binding and LiveData

MVVM is the architectural pattern that follows Single Responsibility Principle providing enough flexibility to the application.

Data binding is anyway an essential component to execute MVVM and it strengthens the MVVM. Data binding is the process of binding the Data Source data to Consumers.

In other words, it is all about binding the data of local storage or network to the layout. Auto-synchronization of data changes between Data Sources and Consumers is its one of the most significant advantages.

LiveData is an observable holder class that is linked with component lifecycle. It prevents the possibilities of memory leaks by releasing unused allocated memory, if any component of activity/Fragment/Service destroys by chance.

Using them together lead us to the development of robust, testable and easy to maintain architectural pattern for an Android application.

Executing MVVM combined with Data Binding and LiveData for an Android App

Step 1: Basic set up to enable Data Binding in Gradle

android {
    compileSdkVersion 27
    defaultConfig {
   
    }
    
    // Enabling databinding
    dataBinding {
        enabled = true
    }
}
dependencies {
      …..
      ….
     // ViewModel and LiveData
    implementation 'android.arch.lifecycle:extensions:1.1.0'
    // Lifecycle
    implementation 'android.arch.lifecycle:runtime:1.1.0'
    // For observable patterns
    compile "io.reactivex.rxjava2:rxjava:2.1.10"
    compile "io.reactivex.rxjava2:rxandroid:2.0.2"

    // Dependency injection using Dagger
    implementation "com.google.dagger:dagger:2.11"
    annotationProcessor "com.google.dagger:dagger-compiler:2.11"
    annotationProcessor "com.google.dagger:dagger-android-processor:2.11"
     implementation "com.google.dagger:dagger-android-support:2.11"
}

Step 2: Create the relevant class i.e. BaseViewModel and extend it to ViewModel or AndroidViewModel

We need to create a BaseViewModel to extend the ViewModel. It will take care of basic stuff such as Network Requirements, DatabaseManager etc. Extend it to ViewModel or AndroidViewModel as displayed below

public abstract class BaseViewModel extends ViewModel {
    private final NetworkUtils networkUtils;
    private final DataManager dataManager;
    private CompositeDisposable compositeDisposable;
    private final SchedulerProvider schedulerProvider; 

    BaseViewModel(DataManager dataManager, NetworkUtils networkUtils,
                  SchedulerProvider schedulerProvider) {
        this.dataManager = dataManager;
        this.networkUtils = networkUtils;
        this.schedulerProvider = schedulerProvider;
        this.compositeDisposable = new CompositeDisposable();
}

Step 3: Create ViewModel for Login Module.

ViewModel will look after module business logic and all respective events related to Activity, Fragments and any other lifecycle component. This is going to be a reusable ViewModel.

public class ViewModelLogin extends BaseViewModel {

    public Handler mHandler;

    public ViewModelLogin(DataManager dataManager, NetworkUtils networkUtils, SchedulerProvider
            schedulerProvider) {
        super(dataManager, networkUtils, schedulerProvider);
        addListener(); 
    }
    ...
    ...
}

Now, we need to execute addListener() as displayed below: addListener() will initialise the call back events to be provided by View using dataBinding

public void addListener() {

    mHandler = new Handler() {
        @Override
        public void onClick(View view) {
            …
            else if (view.getId() == R.id.button_signin) {
                checkValidation();
            }
            ...
            ...
        }
    };
}

Create a Login class, which extends base fragments with ViewModel Login Class, which we have created earlier and it will be responsible for Validations and Service Calls

public class FragmentLogin extends BaseFragment<ViewModelLogin>

Additionally, we have created a DI for ViewModelLogin to make the application more independent. You can create any dI as per your requirement.

@Inject	
ViewModelProvider.Factory factory; 
private ViewModelLogin mViewModelLogin;

Replace ViewModelProviders to mViewModelLogin

mViewModelLogin = ViewModelProviders.of(this, factory).get(ViewModelLogin.class);

You can call any relevant method of that class using the above variable. For example, if you want to call Forgot Password Method, you can call

mViewModelLogin.callForgotPasswordRequest(emailId);

Step 4: Enable Override, if required

ViewModel is tightly coupled to Component Lifecycle and will take care of the entire application lifecycle. However, there will be cases when you might have forwarded lifecycle events to the ViewModel from Fragments and Activities. In case of requirement, you can utilize the possibility to release resource when the Activity gets completely destroyed. Simply override onCleared() to cancel long running operations for example, you can override as displayed below to network related calls.

@Override
protected void onCleared() {
    compositeDisposable.dispose();
    super.onCleared();
}

Step 5: Execute Data binding to enable View interact with ViewModel

Bind View with business logic as displayed below:

[i] Wrap your activity or fragment layout with <layout>… </layout> tag

<layout xmlns:android=http://schemas.android.com/apk/res/android
     ... >
    <!--  Your actual layout will goes here  -->
</layout>
[ii] Inject your ViewModel into you layout(View) using <data> tag

<layout xmlns:android=http://schemas.android.com/apk/res/android
     ... >
    <data>
        <variable
            name="viewmodelLogin"
            type="com.azilen.viewmodel.ViewModelLogin" />
        </data>
</layout>
[iii] Pass events to ViewModel using variable injected viewmodelLogin.

<Button
    android:id="@+id/button_signin"
    ...
    ...
    android:onClick="@{ viewmodelLogin .handler::onClick}"/>

To define how View will get notified about the changes in items or data it is bound to, you have couple of options to choose as per your suitability:

[1] Expose public instances of ObservableField

[2] Bind the Views to methods instead of fields, and use notifyPropertyChanged manually

Pitfall to be avoided: Don’t pass any View or Activity into ViewModel as it is not right way to execute MVVM and may cause memory leaks.

 

Conclusion:

In this blog, we have executed MVVM combined with Data binding and LiveData with an example of Login Module for an Android app. This combination enables us to build the architectural pattern that remarkably reduces the effects of any kind of change in View or Business Logic as well as safeguards the memory leak issues.

 

About Author:

Kutbi is a techie spirited Software Engineer at Azilen Technologies and has 7 years of experience in Android Development. He loves both vigorous coding and experimenting new methods to address the techie world challenges.

 

Add a Comment