Android data-binding framework has been invented more than one year, now I think it’s time to research it and apply it to real project. So I will talk about the MVVM in this post.

I. RoboBinding

Before I talk about the Android data-binding framework, I want to talk about another data-binding library RoboBinding. This library is created way before Android data-binding framework. I got to know this library two years ago, and found it very easy to use. This library uses the compile-time annotation to generate source code of data-binding for you. I have to say, this library is better than today(201703)’s Android data-binding library. Its two-way binding, AdapterView binding is even more easier than Android data-binding library. If you are interested, you can read the source code, and I hope you will enjoy the code.

III. MVVM

For those person who know MVVM is always with data-binding, I have to say, MVVM is not necessarily using data-binding.

In the MVP pattern, our Presenter must know the existance of View, so when you get the data from Model, you can call, like view.refresh(data); . But in MVVM, our middle-layer, ViewModel (not Presenter anymore), does not need know the existance of View, or it does not care about the View. Anyone could be the View, what I(ViewModel) should do is just send the UI logic out, any view can hold it and deal with it.

To fulfill such an architecture, you have at least two ways:

  • Data-Binding : What you should do is just changing the model/data, the data-binding framework will be in charge of deliver this change event to the view.
  • RxJava : This solution is like Observable pattern. The ViewModel just send the change event, and his subscriber will get notified. By the way, ViewModel does not know, and does not need to know which class is the receiver.

step 1. POJO class

We have a User class. And its fields’ change should be sent by notifyPropertyChanged(), and it’s field’s value should be get by @Bindable method. Here is the code:

public class User extends BaseObservable {
    public String name;
    public boolean isMale;

    public User(String name.boolean isMale ) {
        this.isMale = isMale;
        this.name = name;
    }

    public void setIsMale(boolean male) {
        isMale = male;
        notifyPropertyChanged(BR.male); // BR is a class generated by data-binding
    }

    public void setName(String name) {
        this.name = name;
        notifyPropertyChanged(BR.name);
    }


    @Bindable
    public boolean isMale() {
        return isMale;
    }

    @Bindable
    public String getName() {
        returnname; }}Copy the code

step 4. ViewModel

ViewModel takes charge of change of POJO classes, and the click/select/… events.

public class Binding01ViewModel implements ICustomListener{

    private final ActivityBindingDemoSimpleBinding binding;
    private User user;

    public Binding01ViewModel(ActivityBindingDemoSimpleBinding binding) {
        user = new User("szw"."developer".true.R.drawable.ic_face);
        this.binding = binding;
        binding.setUser(user);
        binding.setHandler(this);
    }

    public void click01(View v) {
        System.out.println("szw click01 : " + user);
    }


    public void onChecked(boolean isChecked) {
        user.setName(user.name + (isChecked ? " Y " : " N "));
        System.out.println("szw click02 : " +user); }}Copy the code

  1. The ActivityBindingDemoSimpleBinding class in the constructor is actually a class generated by data-binding. Our layout xml is activity_binding_demo_simple.xml, so the generated class’s name is ActivityBindingDemoSimpleBinding.java.

  2. As shown in the layout xml, we need two variables, one is user, and the other is handler. You have to tell the ActivityBindingDemoSimpleBinding class the two instance, so you have to call binding.setUser() and binding.setHandler().

  3. the click01() and onChecked() methods are the click/checkChanged event method.

  4. Every time the name and isMale changed, our UI will get refreshed too. It’s the beauty of data-binding.

V. OneBindingAdapter

By the way, I personally hate write each Adapter for each RecyclerView. So I did some homework and create a OneBindingAdapter.

The layout of RecyclerView’s each item is “layout/item_rv.xml”

<?xml version="1.0" encoding="utf-8"? > <layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable name="item" type="ca.six.bindingdemo.tmp.rv.TmpItem"/>
    </data>

    <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">
        <TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
            android:textSize="20dp" android:text="@{item.name}"/>
        <TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
            android:textSize="20dp" android:text="@{String.valueOf(item.age)}"/>
    </LinearLayout>

</layout>Copy the code

So after create a layout xml, which contains and view, you can just use this:

    OneBindingAdapter<TmpItem> adapter = new OneBindingAdapter<>(this.R.layout.item_rv, BR.item, data);
    RecyclerView rv = binding.rvBindingDemo;
    rv.setLayoutManager(new LinearLayoutManager(this));
    rv.setAdapter(adapter);Copy the code

  1. the constructor of OneBindingAdapter need the context, item layout resouce, and BR.~.
  2. About the “BR.“, the “” is the element in the layout xml

VI. Conclusion

MVVM is a new pattern and will make your development easier. And it helps you separate the UI and logic, makes unit test avaiable. So why not give it a try?