Android Data Binding Advanced Concepts

Filed Under: Android

In this tutorial we’ll look into some other tricky usages of Data Binding in our application. For a better understanding of this tutorial, do view the Android Data Binding Tutorial.

Android Data Binding Recap

In the previous tutorial we looked into how Data Binding approach removes the need of using findViewById to hookup the UI view objects in our app code.
Another advantage of Data Binding over findViewById is that it enhances the performance of the application.
Using findViewById requires us to lookup the view in the entire hierarchy every time it’s invoked. Thus it requires a single pass through the entire view hierarchy for every child view. On the other hand, Data Binding uses just one single pass and stores all the field names of every child view layout. There’s no need for a second pass since we’ve already found all the views in the first pass itself.

Android Data Binding Overview

Data Binding has lots more to do than just getting rid of findViewById. You must have experienced scenarios where a ListView or a RecyclerView or just a normal layout for the sake uses a data model to add the relevant information into the layout. Even if we get the field names of the view layouts in our MainActivity it still requires us to write a lot of repetitive code snippets. Let’s say we have a layout where we’re adding data from a DataModel.java class dynamically and updating the values after a specific interval. The following code snippet shows an example implementation of Data Binding when the data is supplied to the layout from a Data Model class.

activity_main.xml


<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">


        <ImageView
            android:id="@+id/imageView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

        <TextView
            android:id="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

        <TextView
            android:id="@+id/summary"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>
</layout>

The DataModel.java class is given below.


public class DataModel {

    String name;
    int image;
    String summary;


    public DataModel(int image, String name, String summary) {

        this.name = name;
        this.summary = summary;
        this.image = image;
    }

    public int getImage() {
        return image;
    }

    public void setImage(int image) {
        this.image = image;
    }

    public String getName() {
        return name;
    }

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

    public String getSummary() {
        return summary;
    }

    public void setSummary(String summary) {
        this.summary = summary;
    }
}

The MainActivity.java is given below.


public class MainActivity extends AppCompatActivity {

    ActivityMainBinding binding;
    Timer timer;
    int i = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

        DataModel dataModel = new DataModel(R.drawable.marsh, "Android MarshMallow", "Android 6.0");
        binding.imageView.setImageResource(dataModel.getImage());
        binding.name.setText(dataModel.getName());
        binding.summary.setText(dataModel.getSummary());

        timer= new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {

                        if (i == 0) {
                            DataModel dataModel = new DataModel(R.drawable.lollipop, "Android Lollipop", "Android 5.0");
                            binding.imageView.setImageResource(dataModel.getImage());
                            binding.name.setText(dataModel.getName());
                            binding.summary.setText(dataModel.getSummary());

                            i=1;

                        } else {
                            
                            i=0;
                            DataModel dataModel = new DataModel(R.drawable.marsh, "Android MarshMallow", "Android 6.0");
                            binding.imageView.setImageResource(dataModel.getImage());
                            binding.name.setText(dataModel.getName());
                            binding.summary.setText(dataModel.getSummary());

                        }
                    }
                });
            }
        }, 3000, 3000); 
    }
}

We’ve used a timer that keeps changing the layout data alternately after every 3 seconds.
As you can see there is too much repetitive code for setText and setImageResource.
DataBinding allows us to directly assign the data from the DataModel class inside our xml layout. We’ll see how.

Android Data Binding Project Structure

android data binding

Android Data Binding Code

We define the DataModel class variable object in the xml as shown in the layout below.

activity_main.xml


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

    <data>
        <variable
            name="data"
            type="com.journaldev.advanceddatabinding.DataModel" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/imageView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@{data.image}" />

        <TextView
            android:id="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{data.name}" />

        <TextView
            android:id="@+id/summary"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{data.summary}" />
    </LinearLayout>
</layout>

DataBinding has its own expression language for layout files. It allows us to assign the data directly in the xml attributes.

  • <data> is put in the layout and serves as as wrapper for variables used in the layout tag can also be used to import types we need in your work example a View type as shown below:
    
    <data>
        <import type="android.view.View" alias="v"/>
    </data>
    

    The alias attribute is used to assign the import type a name for convenience.

  • <variable> contains name and type describing the name of the variable and its full name respectively (including the package name)
  • @{} container used for describing the expression. For example, displaying field names or displaying data using expressions and operators(we’ll look at this later)

The MainActivity.java is given below.


public class MainActivity extends AppCompatActivity {

    ActivityMainBinding binding;
    Timer timer;
    int i = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

        DataModel dataModel = new DataModel(R.drawable.marsh, "Android MarshMallow", "Android 6.0");
        binding.setData(dataModel);

        timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if (i == 0) {
                            DataModel dataModel = new DataModel(R.drawable.lollipop, "Android Lollipop", "Android 5.0");
                            binding.setData(dataModel);
                            i = 1;
                        } else {
                            i = 0;
                            DataModel dataModel = new DataModel(R.drawable.marsh, "Android MarshMallow", "Android 6.0");
                            binding.setData(dataModel);
                        }
                    }
                });
            }
        }, 3000, 3000); // End of your timer code.
    }

    @BindingAdapter({"android:src"})
    public static void setImageViewResource(ImageView imageView, int resource) {
        imageView.setImageResource(resource);
    }
}

Doesn’t it look a lot cleaner and more readable now!

Few inferences drawn from the above code:

  • The DataModel object is directly set to binding object as
    binding.setData(dataModel);.
    The method setData is generated from the variable name defined in the xml layout
  • ImageView is a source attribute. For the BindingAdapter to recognise the android:src attribute we explicitly define it in the MainActivity.java as
    
    @BindingAdapter({"android:src"})
        public static void setImageViewResource(ImageView imageView, int resource) {
            imageView.setImageResource(resource);
        }
    

Android Data Binding App Output

The output of the application in action is given below.
android data binding advanced concepts

The expression language provided by DataBinding has much more to use than just specifying the data.
We can specify the xml attributes based on certain conditions as shown below.


android:text="@{data.name != null ? data.name : data.summary}"

The above line can be be written in a more compact form:


android:text="@{data.name ?? data.summary}"

This brings an end to this tutorial. You can download the Android AdvanceDataBinding Project from the below link.

Comments

  1. Karanbeer says:

    how to update the layout .to get the values from the sharedprefrences using data binding

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages