MVVM Architecture For Android

Google introduced Android Architecture Components which included ViewModel rather than Presenter and hence the proof that even Google is supporting MVVM.

Technology & Product
 — 
10 Min read
 — 
February 14, 2021

In software engineering, a design pattern is a common occurring problem in software design. A design pattern is not a final design that can be transformed directly into code.solved

One major problem in software development is tight coupling of code i.e. even a small change in one portion of code results in change or bugs in some other part of code. Code is not unit test friendly and code is not reusable.

Introduction

Currently, many architectural approaches are available like MVP,FLUX,MVI,MVVM that are solving above problems. We can use any approach to maintain our code in proper manner so that everything works well, in short a happy developer life. In this article, we are discussing about MVVM design pattern in android and how we can solve existing problems with MVVM design pattern.

The main component in MVVM design pattern are : 

  1. View - Informs the ViewModel about the user’s actions
  2. ViewModel - Exposes streams of data relevant to the View
  3. DataModel - Abstracts the data source. The ViewModel works with the DataModel to get and save the data.

Brief Explanation of MVVM Design Pattern

Google introduced Android Architecture Components which included ViewModel rather than Presenter and hence the proof that even Google is supporting MVVM.


ViewModel

ViewModels are simple classes that interact with the logic/model layer and just expose states/data and actually has no idea by whom or how that data will be consumed. Only View(Activity) holds the reference to ViewModel and not vice versa, this solves our tight coupling issue. A single view can hold a reference to multiple ViewModels.

public class MainViewModel extends ViewModel {
  public MainViewModel() {
  }

  public String getText() {
  return new DataModel().getText();
}
}
View

In android, activity represents a view in MVVM design pattern.The View is responsible for visual display of applications, along with data input by users. This part should not process the data under any circumstances. Its function is only to detect the input like touch or swipe and visualization.

The ModelView-ViewModel architectural pattern has been introduced to Android with the birth of DataBinding library.You can  enable databinding from app.gradle.

dataBinding {
  enabled = true
}

Add these lines in app.gradle inside android{} tag.  Then put your xml layout code under <layout></layout> tag. This will generate binding class and you can access this class from activity. You can see, we can directly access getText() method from xml.

<?xml version="1.0" encoding="utf-8"?>

<layout>
  <data>
      <variable
          name="mainViewModel"
          type="com.g.mvvmproject.MainViewModel" />
  </data>

  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto"
      xmlns:tools="http://schemas.android.com/tools"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      tools:context=".MainActivity">

      <TextView
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="@{mainViewModel.text}"
          app:layout_constraintBottom_toBottomOf="parent"
          app:layout_constraintLeft_toLeftOf="parent"
          app:layout_constraintRight_toRightOf="parent"
          app:layout_constraintTop_toTopOf="parent" />

  </RelativeLayout>

</layout>

After setContentView in activity you set a reference of view model.


public class MainActivity extends AppCompatActivity {

  private ActivityMainBinding mActivityMainBinding;
  private MainViewModel mainViewModel;


  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      mActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
      mainViewModel = new MainViewModel();
      mActivityMainBinding.setMainViewModel(mainViewModel);
  }
}

DataModel

DataModel holds the data of the application. It cannot directly talk to the View. Generally, it’s recommended to expose the data to the ViewModel through Observables.


public class DataModel {

  String text="Hello World ";

  public String getText() {
      return text + text;
  }
}

Advantages of using MVVM Design Pattern

  • Your code testability is increased.

In below code snipped, we test getText() method in ViewModel. You can mock your data and check expected result.

@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {

  @Test
  public void emailValidator_CorrectEmailSimple_ReturnsTrue() {
      String expected = "Hello World Hello World ";
      assertEquals(expected, new MainViewModel().getText());
  }
}

  • Your code is decoupled.
  • The package structure is even easier to navigate.
  • The project is even easier to maintain.
  • Your team can add new features even more quickly.

Conclusion

MVVM combines the advantages of separation of concerns provided by MVP, while leveraging the advantages of data bindings. The result is a pattern where the model drives as many operations as possible, minimizing the logic in the view.

A simple example of the MVVM implementation can be found here.

Like the article? Spread the word