Android — Implementing Recycler View (Part-I)

Hari Vignesh Jayapalan
7 min readFeb 8, 2016

--

RecyclerView is a flexible view for providing a limited window to a large result or data set. Android apps using Listview, for implementing news feeds or contact lists will be likely to face performance issues or unnecessary lags when the user scrolls the view fast. RecyclerView takes over the Listview with improved performance and it provides fluid scroll experience for the user.

Why is it called as RecyclerView? Why is it faster ?

With respect to the Listview, each time the layout is inflated or created based on the data set. But RecyclerView creates only the views that are required for displaying in the viewport/screen of the mobile, along with few views on top and bottom of the viewport or screen.

When the user scrolls, the views which go out the screen/viewport of the mobile are recycled or taken back to the bottom with new data set values. This operation is taken care by the ReyclerView automatically. Thus, our mystery is solved.

RecyclerView architecture is slightly different from the Listview architecture. Let’s see what the official documentation tells us.

Layout Manager: It positions item views inside a RecyclerView and determines when to reuse item views that are no longer visible to the user. To reuse (or recycle) a view, a layout manager may ask the adapter to replace the contents of the view with a different element from the data set. Recycling views in this manner improves performance by avoiding the creation of unnecessary views or by performing expensive findViewById() lookups.

RecyclerView provides these built-in layout managers:

  • LinearLayoutManager shows the items in vertical or horizontal scrolling list.
  • GridLayoutManager shows the items in a grid.
  • StaggeredGridLayoutManager shows the items in a staggered grid.

Also, to create a custom layout manager, we need to extend RecyclerView.LayoutManager class

Implementing RecyclerView

First let’s create a new Android project using Android Studio with a Main Activity (Just for fun, I’ve created a Scrolling Activity).

Importing RecyclerView into the Project

Add the following Gradle dependency project into the build.gradle file of the app module

compile 'com.android.support:recyclerview-v7:23.1.1'

In the XML file of the MainActivity, add the RecyclerView Component.

<android.support.v7.widget.RecyclerView
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="@+id/recycleView"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
</android.support.v7.widget.RecyclerView>

Creating POJO class

POJO is an Acronym for Plain Old Java Object. It is a normal Java object class and does not serve any other special role nor does it implement any special interfaces of any of the Java frameworks. This term was coined by Martin Fowler, Rebbecca Parsons and Josh MacKenzie who believed that by creating the acronym POJO, such objects would have a “fancy name”, thereby convincing people that they were worthy of use. — source

Create a new Class (I’ve named as CustomPojo) and define the get() and set() methods for the data. In this example I’m sending and receiving name, time and content (Like Whatsapp chat).

public class CustomPojo {

//POJO class consists of get method and set method
private String name;
private String time,content;
private ArrayList<CustomPojo> customPojo =new ArrayList<>();

public CustomPojo() {

}
//getting content value
public String getContent(){return content;}
//setting content value
public void setContent(String content){this.content=content;}

public String getTime(){return time;}
public void setTime(String time){this.time=time;}

public String getName() {
return name;
}

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

}

Creating a Custom View

We need to have a custom row item for the RecyclerView to inflate on each iteration. I have created a simple layout, an ImageView with static image value(can be made dynamic by implementing any one of the image libraries like Picasso, Volley Network Image Library or Glide), and three TextViews to bind username, time and content.

<!--Name of the file: custom_row.xml --><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="72dp"
android:padding="6dip"
android:clickable="true">

<ImageView
android:id="@+id/picture"
android:layout_width="45dp"
android:layout_height="45dp"
android:padding="0dp"
android:src="@mipmap/avatar"
android:layout_marginLeft="16dp"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginStart="19dp" />

<TextView
android:id="@+id/content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:singleLine="true"
android:text="Content"
android:textSize="12sp"
android:paddingLeft="5dp"
android:textColor="@color/colorSecondaryText"
android:layout_below="@+id/user_name"
android:layout_alignParentRight="true"
android:layout_marginLeft="72dp"
android:layout_marginRight="16dp" />

<TextView
android:id="@+id/user_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignWithParentIfMissing="true"
android:gravity="center_vertical"
android:text="Username"
android:textSize="14sp"
android:paddingLeft="5dp"
android:textColor="@color/colorPrimaryText"
android:layout_alignTop="@+id/picture"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_marginLeft="72dp"
android:layout_marginRight="16dp"
android:paddingBottom="5dp" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="time"
android:id="@+id/time"
android:textSize="10sp"
android:textColor="@color/colorSecondaryText"
android:layout_below="@+id/user_name"
android:layout_alignRight="@+id/content"
android:layout_alignEnd="@+id/content" />

</RelativeLayout>

This xml file will look similar to the image below

Creating Adapter Class

An Adapter object acts as a bridge between an AdapterView and the underlying data for that view. The Adapter provides access to the data items. The Adapter is also responsible for making a View for each item in the data set. - source

Create a new class (I’ve named it as CustomAdapter) and extend RecyclerView.Adapter<”yourAdapterClassName.YourViewHolderClassName”> class

This will Override three important methods

  • onCreateViewHolder()
  • onBindViewHolder()
  • getItemCount()

onCreateViewHolder() is called when RecyclerView needs a new RecyclerView.ViewHolder of the given type to represent an item.This new ViewHolder should be constructed (which we will be doing in a while) with a new View that can represent the items of the given type. You can either create a new View manually or inflate it from an XML layout file.

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
view=inflater.inflate(R.layout.custom_row, parent, false);
holder=new MyViewHolder(view);
return holder;
}

onBindViewHolder() is called by RecyclerView to display the data at the specified position. This method should update the contents of the itemView to reflect the item at the given position.

@Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
CustomPojo list_items=list_members.get(position);
holder.user_name.setText(list_items.getName());
holder.content.setText(list_items.getContent());
holder.time.setText(list_items.getTime());
}

getItemCount() is called by the RecyclerView to get the number of items inflated or present in it.

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

Now, Let’s create a ViewHolder class (a subclass inside the Adapter class and I’ve named it as MyViewHolder) and extend RecyclerView.ViewHolder

class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
TextView user_name,content,time;
public MyViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
user_name=(TextView)itemView.findViewById(R.id.user_name);
content=(TextView)itemView.findViewById(R.id.content);
time=(TextView)itemView.findViewById(R.id.time);

}

@Override
public void onClick(View v) {

}
}

The Textview components defined here is for the file custom_row.xml.

To get the values from ArrayList, let’s create a custom method called setListContent()

public void setListContent(ArrayList<CustomPojo> list_members){
this.list_members=list_members;
notifyItemRangeChanged(0,list_members.size());
}

The entire CustomAdapter looks like below

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.MyViewHolder> {

//Creating an arraylist of POJO objects
private ArrayList<CustomPojo> list_members=new ArrayList<>();
private final LayoutInflater inflater;
View view;
MyViewHolder holder;
private Context context;

public CustomAdapter(Context context){
this.context=context;
inflater=LayoutInflater.from(context);
}
//This method inflates view present in the RecyclerView
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
view=inflater.inflate(R.layout.custom_row, parent, false);
holder=new MyViewHolder(view);
return holder;
}

//Binding the data using get() method of POJO object
@Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
CustomPojo list_items=list_members.get(position);
holder.user_name.setText(list_items.getName());
holder.content.setText(list_items.getContent());
holder.time.setText(list_items.getTime());
}

//Setting the arraylist
public void setListContent(ArrayList<CustomPojo> list_members){
this.list_members=list_members;
notifyItemRangeChanged(0,list_members.size());

}

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

//View holder class, where all view components are defined
class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
TextView user_name,content,time;
public MyViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
user_name=(TextView)itemView.findViewById(R.id.user_name);
content=(TextView)itemView.findViewById(R.id.content);
time=(TextView)itemView.findViewById(R.id.time);
}
@Override
public void onClick(View v) {

}
}
public void removeAt(int position) {
list_members.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(0, list_members.size());
}

}

Passing values to the RecyclerView

Back to the MainActivity, where we need to define recyclerView and set it’s layout properties. In this case we need to display as list so, we need to set LinearLayoutManager to the LayoutManager of the RecyclerView. The entire content of our MainActivity is given below (check the comments in the code for deeper understanding)

public class MainActivity extends AppCompatActivity {
//Declare the Adapter, RecyclerView and our custom ArrayList
RecyclerView recyclerView;
CustomAdapter adapter;
private ArrayList<CustomPojo> listContentArr= new ArrayList<>();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView=(RecyclerView)findViewById(R.id.recycleView);
//As explained in the tutorial, LineatLayoutManager tells the RecyclerView that the view
//must be arranged in linear fashion
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter=new CustomAdapter(this);
//Method call for populating the view
populateRecyclerViewValues();
}

private void populateRecyclerViewValues() {
/** This is where we pass the data to the adpater using POJO class.
* The for loop here is optional. I've just populated same data for 50 times.
* You can use a JSON object request to gather the required values and populate in the
* RecyclerView.
* */
for(int iter=1;iter<=50;iter++) {
//Creating POJO class object
CustomPojo pojoObject = new CustomPojo();
//Values are binded using set method of the POJO class
pojoObject.setName("Hari Vigensh Jayapalan");
pojoObject.setContent("Hello RecyclerView! item: "+iter);
pojoObject.setTime("10:45PM");
//After setting the values, we add all the Objects to the array
//Hence, listConentArr is a collection of Array of POJO objects
listContentArr.add(pojoObject);
}
//We set the array to the adapter
adapter.setListContent(listContentArr);
//We in turn set the adapter to the RecyclerView
recyclerView.setAdapter(adapter);
}
}

So, our RecyclerView, Adapter and POJO class are all ready. Let’s run our project.

Et voila !! Here is our output !

Additional Resources

Fork me on GitHub

Check out the complete source code in the following link: https://github.com/Hariofspades/CustomRecyclerView

--

--

Hari Vignesh Jayapalan

Android Dev at WeTransfer| ex Backbase | #1 Google AAD | Public Speaker | Blogger | Creative Coder & Logical Designer