Android Data Binding In RecyclerView

Android Data Binding In RecyclerView

Though it took a while, android has finally given a thought to bring-in data binding. Right now (Aug 7 2015) google states that data binding is still in beta testing and developers should consider the risk factor of including it in their projects. Never the less i got it Working and its pretty cool how it reduced the lines of code and also the easiness it brought-in to development.

Before Starting-of Make sure

  1. Update Android Studio Version is 1.3 or higher
  2. you install the latest android SDK via SDK manager in android studio

Lets get started.  In this post we are gonna just learn what is data binding and the simplest ways to use it (RecyclerView).

Data Binding – Is an plugin used in android studio to bind the model data into views.

Adding the plugin:

-> Go to Top Level build.gradle file and add these two lines as dependencies

classpath "com.android.tools.build:gradle:1.3"
classpath "com.android.databinding:dataBinder:1.0-rc1"

-> Make sure you have jcenter as your repositories.

-> Now goto build.gradle in your module and add these dependencies and add the following right below com.android.application plugin 

apply plugin: 'com.android.databinding'

-> Now add the following lines as dependencies.
compile 'com.android.support:appcompat-v7:22.2.1'
compile 'com.android.support:recyclerview-v7:22.2.1

I intend to display a list of users. In precise a user’s FIRST NAME and LAST NAME . So lets go ahead and create a model .

-> create a class named as USER and paste the following code in it.

[code language=”css”]
public class User {
public final String firstName;
public final String lastName;
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}

}

[/code]

->  Next we will add recycler view to our activity_main.xml , i have used Relative layout as base layout but you are free to use any other layouts.

[code language=”css”]
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="5dp" />
</RelativeLayout>[/code]

-> Lets also design our each_row.xml file for recyclerview – This is where Data Binding pitches in

[code language=”css”]<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data> <variable name="user" type="android.liftoff.com.androiddatabinding.models.User"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/first_name_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
<strong> android:text="@{user.firstName}"</strong> />
<TextView
android:id="@+id/last_name_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp" <strong>
android:text="@{user.lastName}"</strong> />
</LinearLayout> </layout>[/code]

As you observe we have layout tag and variable tag as new entry.

[code language=”css”]<layout xmlns:android="http://schemas.android.com/apk/res/android"> [/code]

and

[code language=”css”]
<data> <variable name="user" type="android.liftoff.com.androiddatabinding.models.User"/> </data>[/code]

<layout> tag enclose the whole layout signifying its an binding layout.

<variable> tag holds the data model which we want to bind into this view.

so in our example we want to show user’s first name and last name in the text views

so in we set the text of first_name_tv    as

[code language=”css”]android:text="@{user.firstName}"[/code]

and set the text of last_name_tv as

[code language=”css”]android:text="@{user.lastName}"[/code]

that’s it and the binding is done in xml.

-> Now lets create an adapter for our recycler view . create a class called RecyclerViewAdapter.

create a constructor and declare the following fields.

[code language=”css”]public class RecyclerViewAdapter{
private Context mContext;
private ArrayList&lt;User&gt; mUsersList = null;
private LayoutInflater inflater;

public RecyclerViewAdapter(Context context, ArrayList&lt;User&gt; usersList) {
mContext = context;
mUsersList= usersList;
inflater = LayoutInflater.from(mContext);
}
}[/code]

-> extend the recycler view adapter of type MyViewHolder and you code should look something like this after implementing the adapter methods.

[code language=”css”]public class RecyclerViewAdapter extends RecyclerView.Adapter&lt;RecyclerViewAdapter.MyViewHolder&gt; {
{ private Context mContext; private ArrayList&lt;User&gt; mUsersList = null;
private LayoutInflater inflater;
public RecyclerViewAdapter(Context context, ArrayList&lt;User&gt; usersList)
{ mContext = context; mUsersList= usersList; inflater = LayoutInflater.from(mContext); }

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return null;
}

@Override
public void onBindViewHolder(MyViewHolder holder, int position) {

}

@Override
public int getItemCount() {
return 0;
}
public class MyViewHolder extends RecyclerView.ViewHolder {
public MyViewHolder(View itemView) {
super(itemView);
}
}
}
}[/code]

-> return the list count inside getItemCount() function

[code language=”css”]public int getItemCount() { return mUsersList.size(); }[/code]

Here comes the cool part.

The databinding library creates a class with the same name of the xml where we did the data binding . The class name ends with “Binding” .This class contains all the binding related information .about view and the model and the mappings. 

In our case the xml file name was each_row.xml so the class generated is EachRowBinding

Instead of inflating the view and sending it to view holder. we send the binding EachRowBinding object.

[code language=”css”]
@Override public MyViewHolder onCreateViewHolder(ViewGroup viewGroup, int i)
{ EachRowBinding binding = EachRowBinding.inflate(inflater);
MyViewHolder myViewHolder = new MyViewHolder(binding);
return myViewHolder; }[/code]

bind the user data as follows in onBindViewHolder() as follows

[code language=”css”]
@Override public void onBindViewHolder(MyViewHolder myViewHolder, int i)
{ User user = mUsersList.get(i);
myViewHolder.vBinding.setUser(user);
}
setUser() is a function generated to set the user data from model to the view.

so now your adapter class should look as below
[code language="css"]
package android.liftoff.com.androiddatabinding.adapters;
import android.content.Context;
import android.liftoff.com.androiddatabinding.databinding.EachRowBinding;
import android.liftoff.com.androiddatabinding.models.User;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;

import java.util.ArrayList;

/**
* Created by nikhil on 6/8/15.
*/

public class RecyclerViewAdapter extends RecyclerView.Adapter&lt;RecyclerViewAdapter.MyViewHolder&gt; {

private Context mContext;
private ArrayList&lt;User&gt; mUsersList = null;
private LayoutInflater inflater;

public RecyclerViewAdapter(Context context, ArrayList&lt;User&gt; usersList) {
mContext = context;
mUsersList= usersList;
inflater = LayoutInflater.from(mContext);
}

@Override
public MyViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
// View view = inflater.inflate(R.layout.each_row,viewGroup,false);
EachRowBinding binding = EachRowBinding.inflate(inflater);
MyViewHolder myViewHolder = new MyViewHolder(binding);
return myViewHolder;
}

@Override
public void onBindViewHolder(MyViewHolder myViewHolder, int i) {
User user = mUsersList.get(i);
myViewHolder.vBinding.setUser(user);
}

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

public class MyViewHolder extends RecyclerView.ViewHolder {
EachRowBinding vBinding;
public MyViewHolder(EachRowBinding binding) {
super(binding.getRoot());
this.vBinding = binding;
}
}
} [/code]

now lets wire things up in MainActivity file.

[code language=”css”]
package android.liftoff.com.androiddatabinding.activities;

import android.liftoff.com.androiddatabinding.R;
import android.liftoff.com.androiddatabinding.adapters.RecyclerViewAdapter;
import android.liftoff.com.androiddatabinding.models.User;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.Menu;
import android.view.MenuItem;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
RecyclerViewAdapter recyclerViewAdapter = new RecyclerViewAdapter(this,getUsersList());
recyclerView.setAdapter(recyclerViewAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();

//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}

return super.onOptionsItemSelected(item);
}

public ArrayList&lt;User&gt; getUsersList() {
ArrayList&lt;User&gt; usersList = new ArrayList&lt;&gt;();

usersList.add(new User("firstUser1","lasuserUser1"));
usersList.add(new User("firstUser2","lasuserUser2"));
usersList.add(new User("firstUser3","lasuserUser3"));
usersList.add(new User("firstUser4","lasuserUser4"));

return usersList;
}
} [/code]

As you see i have created Initialized the recycler view and set the adapter (RecyclerViewAdapter) to it. I also created getUsersList() to get a list of users so that we can pass it to the adapter. Now build the project and run it . pretty sure it works . Have fun coding…