Recent Posts

Those who are free of resentful thoughts surely find peace. - Buddha

MVVM - Part2

Posted on 27th Nov 2017


<-Back to Blogs

Model View ViewModel architecture

model-view-viewmodel

Now let’s look at the ModelViewViewModel architecture and how the three components in this architectural pattern work together.

  • The view is the user interface, the layout. In Android this usually means an Activity, Fragment or ViewHolder and its corresponding inflated xml layout file.
  • The model is our business logic layer, which provides methods for interacting with data.
  • The view model acts as a middleman between view and model, by exposing the data from the model via properties and containing the UI state. Also, it defines commands which can be called on events like clicks. View models contain the presentation logic of your app.

In the MVVM architectural pattern, the view and the view model mainly interact with each other through data binding. Ideally, the view and view model should not know about each other. The bindings should be the glue between view and view model and handle most of the stuff in both directions. In Android however, they can not really be independent:

  1. you have to save and restore state, but the state is now in the view model.
  2. you need to tell your view model about lifecycle events.
  3. you might encounter situations where you need to call view methods directly.

For these cases, both the view and the view model should implement interfaces, which are then used for communication via commands, if necessary. In almost all cases, however, only an interface for the view model is needed, since the data binding library handles the interactions with the view, and custom components can be used e.g. when a context is needed.

The view model also updates the model, e.g. by adding a new element to the database or updating an existing one. It is also used to fetch data from the model. Ideally, the model should also notify the view model of changes, but this depends on the implementation.

Now, generelly speaking, the separation of view and view model makes the presentation logic easily testable and also helps with maintenance in the long run. Together with the data binding library this means less code and cleaner code.

<layout xmlns:android="...">
  <data>
    <variable name="vm" type="pkg.MyViewModel" />
  </data>
 
  <FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">
 
    <EditText
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:visibility="@{vm.shouldShowText}"
      android:text="@={vm.text}" />
 
    <Button
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:onClick="@{vm::onButtonClick}"
      android:text="@string/button"/>
  </FrameLayout>
</layout>
 
When you want to use MVVM architecture, your layouts should only reference one variable, the specific view model for this view, in this case MyViewModel. In the view model, you provide properties for the layout. This can be as easy as returning a String from a model object or more complex, depending on your use case.
 
public class MyViewModel extends BaseObservable {
   private Model model = new Model();
 
   public void setModel(Model model) {
       this.model = model;
       notifyChange();
   }
 
   public boolean shouldShowText() {
       return model.isTextRequired();
   }
 
   public void setText(String text) {
       model.setText(text);
   }
 
   public String getText() {
       return model.getText();
   }
 
   public void onButtonClick(View v) {
       // Save data
   }
}

Here we have a text property. As we have an EditText for user input, we can use two way data-binding, to also have the data binding library save the inputs back to the view model. For this, we create both a setter and a getter and bind the property to the text attribute of our EditText, but this time with an = sign before the bracket, which signals the library that we want two way data binding here.

Also, we only want to show the EditText when our model says that text input is required. For this, we provide a boolean property in our view model and bind it to the visibility attribute. For this to work, we also have to create a binding adapter, which sets the visibility to GONE when false and VISIBLE when true.

@BindingAdapter("android:visibility")
public static void setVisibility(View view, boolean visible) {
   view.setVisibility(visible ? View.VISIBLE : View.GONE);
}
 
Finally, we want to store the information when a Button is pressed. For this, we create a command onButtonClick() in our view model, which handles interacting with the model. In the layout, we bind the command to the onClick attribute of the Button via a method reference. For this to work directly, our method needs to have a single parameter of type View, just like an OnClickListener. As an alternative – if you don’t want the View parameter – you could also use lambda expressions directly in the layout. As you can see, it’s quite easy and straight forward to use data binding with a view model.
 
Now, it’s important to remember that we want to put presentation logic in our view model for testability. Avoid putting logic directly in the bindings, even though the data binding library allows it. Don’t forget that you can also have custom binding adapters, which can often simplify things.
 
Hope you like this part of article. In the next part of this article series we would learn about how one can handle LifeCycle and state while implementing MVVM model.


<-Back to Blogs

Categories

Good, better, best. Never let it rest. Untill your good is better and your better is best. - St. Jerome

© SOFTHINKERS 2013-18 All Rights Reserved. Privacy policy