Menu

Android Data Binding

0 Comment

This tutorial describes the usage of data binding in Android applications. Data binding allows to synchronize your user interface with your application model and logic.

Android data binding library provide mechanism for us to bind the data in the Android layout,
and it allows us to remove all the boilerplate findViewById() codes as well as having to manually
update those views in the code.

 

 

I created a demo application, and I would like to share my experiences with this library with you.

What does it offer us?

  • Make findViewById totally obsolete
  • Encourage to separate UI logic and business logic
  • Make easy to synchronize between data sources and UI elements
  • Provides a way to bind event listener using lambda or method reference from xml.

 

1. Enable data binding in your Android application
To enable the usage of data binding in your Android application, add the following snippet to the app/build.gradle file.

android {
....
dataBinding {
enabled = true
}
}

 

2.Add INTERNET permission in AndroidManifest.xml as the images needs to be loaded from an URL.

<uses-permission android:name="android.permission.INTERNET" />

 

3.layout Tag in xml file.

In layout file, generally, we have ViewGroup as top in View hierarchy.
But here, we will make <layout> tag as most parent tag or root tag.
After adding it, build system will process it for data binding:

To enable DataBinding in a layout, the root element should start with <layout> tag.
Along with it, <data> and <variable> tags are used.

 

<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> //Student is the model class with name and mobilenumber parameters <variable name="student" type="com.demoapplication.models.Student" /> <data> <variable name="iNextCallActivity" type="com.demoapplication.view.INextCallActivity"/> </data>


<RelativeLayout
android:id="@+id/view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<LinearLayout
android:id="@+id/ll_login"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical"
android:padding="50dp">

<TextView
android:id="@+id/tv_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/small_margin"
android:text="@{student.name}"
android:textColor="@color/black"
android:textSize="@dimen/feed_date"
android:textStyle="bold" />

<TextView
android:id="@+id/tv_mobilenumber"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/small_margin"
android:text="@{student.mobilenumber}"
android:textColor="@color/black"
android:textSize="@dimen/feed_date"
android:textStyle="bold" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:gravity="center"
android:orientation="horizontal">

<Button
android:id="@+id/btn_login"
style="@style/ButtonStyle"
android:layout_width="wrap_content"
android:layout_marginRight="20dp"
android:onClick="@{() -> iNextCallActivity.onNextScreen()}"
android:text="Next" />

</LinearLayout>

</LinearLayout>

</RelativeLayout>

</layout>

 

4.After above step, binding class will be generated based on same name of layout file
(e.g.demo_activity binding class will be generated DemoActivityBinding ).
We can set setContentView using DataBindingUtil like:

 

import android.content.Intent;
import android.databinding.DataBindingUtil;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.nitor.demoapplication.R;
import com.nitor.demoapplication.databinding.LoginActivityBinding;
import com.nitor.demoapplication.view.detailsList.MedicalListActivity;

public class DemoActivity extends AppCompatActivity implements INextCallActivity {

DemoActivityBinding demoActivityBinding;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

initDataBinding();
}

private void initDataBinding() {
demoActivityBinding = DataBindingUtil.setContentView(this, R.layout.demo_activity);
demoActivityBinding.setINextCallActivity(this);
}

@Override
public void onNextScreen() {
startActivity(new Intent(LoginActivity.this, MedicalListActivity.class));
}
}

 

5.Create a interface INextCallActivity for button click and implements it in DemoActivity.

package com.demoapplication.view;

public interface INextCallActivity {

void onNextScreen();
}

Delcare this in layout file on button click.

android:onClick="@{() -> iNextCallActivity.onNextScreen()}"

 

Data Binding In RecyclerView Android

Data Binding as a term doesn’t always mean Android Data Binding. RecyclerView has its own way of binding data to the UI.
RecyclerView has an Adapter with two very important methods that we implement to bind data:

RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType);

void onBindViewHolder(RecyclerView.ViewHolder holder, int position);

call the appropriate ViewModel methods from the UI. One way to instantiate the binding is to use the DataBindingUtil’s setContentView method.
Calling the binding’s setViewModel method sets the ViewModel variable reference.

 

MedicalListActivity

import android.databinding.DataBindingUtil;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;

import com.nitor.demoapplication.R;
import com.nitor.demoapplication.databinding.DetailListActivityBinding;

public class MedicalListActivity extends AppCompatActivity {

DetailListActivityBinding detailListActivityBinding;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

initRecyclerView();
}

public void initRecyclerView(){
detailListActivityBinding = DataBindingUtil.setContentView(this, R.layout.medical_list_activity);
detailListActivityBinding.rvMedicalList.setLayoutManager(new LinearLayoutManager(this));
detailListActivityBinding.rvMedicalList.addItemDecoration(
new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));

MedicalAdapter adapter =
new MedicalAdapter(MedicalListModel.prepareData(), this);
detailListActivityBinding.rvMedicalList.setAdapter(adapter);
}

}

medical_list_activity.xml

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

</data>

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>

<!-- TODO: Update blank fragment layout -->
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_marginTop="20dp"
android:layout_height="wrap_content">

<android.support.v7.widget.RecyclerView
android:id="@+id/rv_medical_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorWhiteSmoke"
android:scrollbars="none" />

</android.support.v4.widget.SwipeRefreshLayout>

</RelativeLayout>

</layout>


 

 

MedicalAdapter

import android.content.Context;
import android.databinding.DataBindingUtil;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;

import com.nitor.demoapplication.R;
import com.nitor.demoapplication.databinding.ItemLayoutBinding;

import java.util.List;

public class MedicalAdapter extends RecyclerView.Adapter<MedicalAdapter.ViewHolder> {

private List<MedicalListModel> medicalListModels;
private Context context;

public MedicalAdapter(List<MedicalListModel> medicalLst, Context ctx) {
medicalListModels = medicalLst;
context = ctx;
}

@Override
public MedicalAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
ItemLayoutBinding binding = DataBindingUtil.inflate(
LayoutInflater.from(parent.getContext()),
R.layout.item_layout, parent, false);

ViewHolder viewHolder = new ViewHolder(binding);
return viewHolder;
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
MedicalListModel medicalListModel = medicalListModels.get(position);
holder.itemLayoutBinding.setMedical(medicalListModel);

}

@Override
public int getItemCount() {
return medicalListModels.size();
}

public class ViewHolder extends RecyclerView.ViewHolder {
public ItemLayoutBinding itemLayoutBinding;

public ViewHolder(ItemLayoutBinding itemLayoutBinding1) {
super(itemLayoutBinding1.getRoot());
itemLayoutBinding = itemLayoutBinding1;
}
}
}

Here is what we’ve done:

  • Updated the ViewHolder class to use binding, removed view variables from it.
  • Updated onCreateViewHolder so that it creates a Binding instance.
  • Updated onBindViewHolder.

 

item_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
<variable name="medical" type="com.nitor.demoapplication.view.detailsList.MedicalListModel"/>

</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
>
<TextView
android:id="@+id/air_lines"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{medical.name}"
android:textSize="12dp"
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/from_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="@{medical.description}"
android:layout_below="@+id/air_lines"
android:layout_alignParentRight="true"
app:layout_constraintTop_toBottomOf="@+id/air_lines"
app:layout_constraintLeft_toLeftOf="parent"
/>

<TextView
android:id="@+id/cost"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@{medical.price}"
android:layout_below="@+id/from_location"
/>

</RelativeLayout>
</layout>

 

MedicalListModel.java

import java.util.ArrayList;
import java.util.List;

public class MedicalListModel {

public String name;
public String description;
public String price;

public MedicalListModel(String name, String description, String price) {
this.name = name;
this.description = description;
this.price = price;
}

public static List<MedicalListModel> prepareData(){
List<MedicalListModel> medicalListModels = new ArrayList<>();

MedicalListModel medicalListModel = new MedicalListModel("Abacavir sulfate", "A carbocyclic nucleoside with potent selective anti-HIV activity.", "$388");
medicalListModels.add(medicalListModel);
MedicalListModel medicalListModel1 = new MedicalListModel("ACAMPROSATE CALCIUM", "Reduces voluntary ethanol intake by rats. ", "$388");
medicalListModels.add(medicalListModel1);
MedicalListModel medicalListModel2 = new MedicalListModel("ACAMPROSATE CALCIUM", "Product of the oxidation of ethanol and of the destructive distillation of wood. It is used locally, occasionally internally, as a counterirritant and also as a reagent. . ", "$388");
medicalListModels.add(medicalListModel2);
MedicalListModel medicalListModel3 = new MedicalListModel(" ACETIC ACID", "Reduces voluntary ethanol intake by rats. ", "$388");
medicalListModels.add(medicalListModel3);
MedicalListModel medicalListModel4 = new MedicalListModel("ACAMPROSATE CALCIUM", "Product of the oxidation of ethanol and of the destructive distillation of wood. It is used locally, occasionally internally, as a counterirritant and also as a reagent. . ", "$388");
medicalListModels.add(medicalListModel4);
return medicalListModels;
}
}




Visit the Github repository link.

Happy Coding!!

 

Please follow and like us:
0
1+
Tags:

Leave a Reply

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

000webhost logo