Recently, I read some code written by some people, and found that many are useful to DataBinding, often see DataBinding related code can not understand, can not understand, it is really uncomfortable ah, but how to do, who let oneself can not. Can’t start to learn, don’t ask will be too much, must be able to read what others write is what meaning.

This is DataBinding entry level difficulty, please correct any errors. The best way to learn DataBinding is through the official example tutorials.

Before you start, you always have to add dependencies, but DataBinding doesn’t introduce two lines of dependencies like RxJava or other libraries do. Instead, you introduce the following configuration in the app.gradle file:

android {
    ...
    dataBinding {
        enabled = true}}Copy the code

Now that we have dependencies, we can start. Now imagine a scenario where we need to display a piece of text on a TextView. So before we did findViewById and then setText, let’s see what DataBinding does.

First, we need to change the structure of the layout file to something like this.

<layout>
    <data>
    </data>
    <ViewGroup>
    </ViewGroup>
</layout>
Copy the code

Android Studio has automatic replacement support for DataBinding.

The replaced ViewGroup is the original root layout, and the data node is used to define the data.

<data>
    <variable name="content" type="String" />
</data>
Copy the code

The variable content defined in this form is equivalent to String Content. We’ve got the Content variable, and then we need to set it to the TextView. I’m going to set Text with android: Text =”” and the value I’m going to fill in is content, but the syntax is a little different, android: Text =”@{content}” where @ and {} are the values that are used to wrap around it, To distinguish android:text=”content”.

Databinding uses this syntax to set content, and in fact it supports expressions as well as strings. See the documentation for more details. This article will also cover some of them.

In fact, we’re more likely to use Content as a class member variable. Android :text=”@{detail.content}”

<data>
    <variable name="detail" type="me.monster.blogtest.model.MomentDetail" />
</data>
Copy the code

With the variables defined in the layout file, it’s time to go back to the Java file and bind the layout file to the data using DataBinding.

public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        FragmentDetailBinding viewDataBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_detail, container, false);
        View root = viewDataBinding.getRoot();
        mMomentDetail = new MomentDetail();
  			mMomentDetail.setContent("Use DataBinding");
        viewDataBinding.setDetail(mMomentDetail);
        return root;
    }
Copy the code
  1. This code is used in fragments, or in activitiesDataBinding.Util.setContentView(Activity activity, int layoutId)This method.
  2. The FragmentDetailBinding class is generated from the layout file. The rules for the class name are the file name of the layout file +Binding;

Using DataBinding this way, it doesn’t seem to be enough for everyday use. Does the TextView automatically update when the content inside the mMomentDetail changes? Not yet, but in order for our TextView to automatically update the content of our mMomentDetail, we need a couple of other things.

To update the content of mMomentDetail in a timely manner, the traditional way to update the content of mMomentDetail is to manually call setText(). Now DataBinding doesn’t have to. We can define the content of mMomentDetail as a type that can be observed to change, and then automatically update the content on the TextView via DataBinding.

public class MomentDetail {    
    private String content;

    public String getContent(a) {
        return content == null ? "" : content;
    }

    public void setContent(String content) {
        this.content = content; }}Copy the code

So this is the MomentDetail class for TextView that doesn’t automatically update its content, so if you want TextView to update its content automatically, you just change the type of the content. Change to ObservableField

content.

private ObservableField<String> content = new ObservableField<>();

public ObservableField<String> getContent(a) {
    return content;
}

public String getContentValue(a) {
    return content.get();
}

public void setContent(String content) {
    this.content.set(content);
}
Copy the code

In contrast to the normal String type, to change the value of the content, we call the observableField.set (T T) method, and get the value using the observableField.get () method.

DataBinding also includes several other classes that are used the same way.

  • ObservableBoolean
  • ObservableByte
  • ObservableChar
  • ObservableShort
  • ObservableInt
  • ObservableLong
  • ObservableFloat
  • ObservableDouble
  • ObservableParcelable

As I write this blog, I modified the MomentDetail using a Handler delay of a few seconds to simulate click events.

When we observe a lot of data, we can also inherit the self-defined data class from BaseObservable. After the inheritance relationship is generated, the member variables in the data class can be automatically applied to the View when changes occur.

public class MomentDetail extends BaseObservable {
    private String moment;
    private int goodCount;

    @Bindable
    public String getMoment(a) {
        return moment == null ? "" : moment;
    }

    @Bindable
    public int getGoodCount(a) {
        return goodCount;
    }

    public void setContent(String msg) {
        this.moment = msg;
        notifyPropertyChanged(BR.moment);
    }

    public void updateGood(int count) { goodCount = count; notifyPropertyChanged(BR.goodCount); }}Copy the code

Not much different from other data classes except for the @bindable annotation and updating notifyPropertyChanged() when member variables are changed. However, Google recommends using LiveData in conjunction with it.

public class MomentViewModel extends ViewModel {

    private MutableLiveData<String> name = new MutableLiveData<>("Abs");
    private MutableLiveData<Integer> good = new MutableLiveData<>();

    public void setNameValue(String value) {
        name.setValue(value);
    }

    public MutableLiveData<String> getName(a) {
        return name;
    }

    public MutableLiveData<Integer> getGood(a) {
        return good;
    }

    public void setGoodValue(int goodValue) { good.setValue(goodValue); }}Copy the code

Accordingly, change the data type in the layout file.

<variable
    name="viewModel"
    type="me.monster.blogtest.model.MomentViewModel" />
Copy the code

Android :text=”@{viewmodel.name}” {viewmodel.name} It doesn’t bother, we just need to provide a method to process the result of a click.

For example, we have a TextView to click on and display the number of clicks on the current TextView.

public void upGood(a) {
    good.setValue(good.getValue() == null ? 1 : good.getValue() + 1);
}
Copy the code
<TextView
    android:id="@+id/iv_good"
    android:layout_width="wrap_content"
    android:layout_height="40dp"
    android:drawableStart="@drawable/ic_good"
    android:drawablePadding="8dp"
    android:gravity="center"
    android:onClick="@{() -> viewModel.upGood()}"
    android:text="@{String.valueOf(viewModel.good)}" />
Copy the code

However, DataBinding is good, but it still has some shortcomings. For example, when loading an image using a third-party framework like Glide, you still have to findViewById. In fact, DataBinding provides an alternative solution by annotating a static method, And then you can use it in View.

@BindingAdapter({"imageRes"})
public static void loadImage(ImageView imageView, int resId) {
    Glide.with(imageView)
            .load(resId)
            .into(imageView);
}
Copy the code
<ImageView
    android:id="@+id/iv_avatar"
    imageRes="@{viewModel.avatar}"
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:src="@mipmap/avatar_1" />
Copy the code

See the official documentation for more uses of BindAdapter.

In general, DataBinding is not difficult, and it is also very easy to get started, but just start, a lot of times can not touch the head. However, the benefit is obvious. There are no direct or indirect findViewById operations used in fragments or activities. The simplicity of activities and fragments is ensured, so that they can better focus on page jumping and data processing. If they are co-developed with other components of Jetpack, it is expected to be more efficient.

This article aims to learn how to use DataBinding simply. The main content is relatively simple. In fact, RecyclerView and other functions are often used in daily development.

This article was first published on my blog. All the code in this article has been uploaded to GitHub and the code branch is dataBinding.

Related articles recommended:

  • Animate the transitions using MotionLayout
  • To learn a wave of Navigation

Cover image: Photo by Paul Schafer on Unsplash.