Working with RecyclerView in Android
Overview
In
Android 5.0 Lollipop, Android introduced RecyclerView widget. Android
RecyclerView is more advanced version of ListView/ GridView with improved
performance and other benefits. Using RecyclerView and CardView both lists and
grids can be created very easily. It is a modernized version of ListView and
GridView provided by Android.
The
RecyclerView class supports the display of a collection of data. It provides extra features that make more maintainable
code and enforce memory efficient design.
Why
RecyclerView
In
a typical ListView you create a custom row layout with some complex layout
design and inflate that layout in getView() method of List Adapter. After then you
get the views, add some logic and pass that view to the ListView. So ListViews
and GridViews achieve some memory efficiency like-
@Override
public View getView(int position, View
convertView, ViewGroup parent) {
LayoutInflater mInflater =
(LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView =
mInflater.inflate(R.layout.list_item, null);
TextView txtTitle = (TextView) convertView.findViewById(R.id.title);
ImageView imageView = (ImageView)
convertView.findViewById(R.id.icon);
txtTitle.setText("");
imageView.setImageResource(getImageId());
return convertView;
}
ListView
and GridView recycle the item layout (ex. R.layout.list_item), but don’t keep
references to the layout children (ex. R.id.title, R.id.icon). It force you to
call findViewById() for every child of your item layout every time you call
getView(). This makes ListView/GridView scrolling becomes jerky or non-responsive.
To
resolve this problem Android initially provided a solution via View Holder
pattern.
When
you use this pattern, you create a class that becomes an in-memory reference to
all the views needed to fill your layout. The benefit is you set the references
once and reuse them, effectively working around the performance hit that comes
with repeatedly calling findViewById().
@Override
public View getView(int position, View convertView,
ViewGroup parent) {
ViewHolder holder = null;
LayoutInflater mInflater =
(LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item,
null);
holder = new ViewHolder();
holder.txtTitle = (TextView)
convertView.findViewById(R.id.title);
holder.imageView = (ImageView)
convertView.findViewById(R.id.icon);
convertView.setTag(holder);
} else
holder = (ViewHolder)
convertView.getTag();
holder.txtTitle.setText("");
holder.imageView.setImageResource(getImageId());
return convertView;
}
More
on the ViewHolder pattern can be found here –
How recyclerView works and its benefit
As
explained above ViewHolder is an optional pattern for ListView or GridView. If forget
to implement the ViewHolder pattern in your ListView or GridView then scrolling
will result non responsive.
Recycler
view uses ViewHolder to store references of views and recycling the views. So
you do not worry to handle it explicitly. It also comes with default animation.
You can even create your own animations and apply them as needed.
RecyclerView
introduces an additional level of abstraction between the RecyclerView.Adapter and RecyclerView.LayoutManager
to be able to detect data set changes in batches during a layout calculation.
This saves LayoutManager from tracking adapter changes to calculate animations.
It also helps with performance because all view bindings happen at the same
time and unnecessary bindings are avoided.
For
this reason, there are two types of position related methods in RecyclerView:
layout
position:
Position of an item in the latest layout calculation. This is the position from
the LayoutManager's perspective.
adapter
position:
Position of an item in the adapter. This is the position from the Adapter's
perspective.
Using
RecylerView
In
this exercise you create a project which uses the RecyclerView class to display
a list.
Add the
Gradle dependency
Add
the following dependency to your Gradle build file to use RecylerView.
dependencies
compile 'com.android.support:recyclerview-v7:25.1.0
}
Create
Activity Layout
Create
a new file activity_main.xml and recyclerview_item.xml inside layout resource
folder and paste the following snippets.
activity_main.xml
<?xml version="1.0"
encoding="utf-8"?>
<RelativeLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="com.androidjavapoint.recyclerviewexample.MainActivity"
tools:showIn="@layout/activity_main">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical" />
</RelativeLayout>
<RelativeLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="com.androidjavapoint.recyclerviewexample.MainActivity"
tools:showIn="@layout/activity_main">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical" />
</RelativeLayout>
recyclerview_item.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content android:layout_margin="10dp android:orientation="vertical"> <TextView android:id="@+id/employeeName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="18dp" android:textStyle="bold" /> <TextView android:id="@+id/employeeId" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="14dp" /> </LinearLayout>
The
MainActivity.java class is defined below :
package com.androidjavapoint.recyclerviewexample; import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import java.util.ArrayList;
import java.util.List; 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); recyclerView.setHasFixedSize(true); LinearLayoutManager llm = new LinearLayoutManager(this); llm.setOrientation(LinearLayoutManager.VERTICAL); recyclerView.setLayoutManager(llm); List<Employee> employeeList = prepareEmployeeList(); EmployeeListAdapter ca = new EmployeeListAdapter(employeeList); recyclerView.setAdapter(ca); } private List<Employee> prepareEmployeeList() { List<Employee> employeeList = new ArrayList<>(); for (int i = 1; i < 20; i++) { employeeList.add(new Employee("Employee " + i, i * 1000)); } return employeeList; } }
The
EmployeeListAdapter.java class is defined below:
package com.androidjavapoint.recyclerviewexample;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List; class EmployeeListAdapter extends RecyclerView.Adapter<EmployeeListAdapter.CustomViewHolder> {
private List<Employee> mEmployeeList; EmployeeListAdapter(List<Employee> mEmployeeList) { this.mEmployeeList = mEmployeeList; } class CustomViewHolder extends RecyclerView.ViewHolder { TextView employeeName; TextView employeeId; CustomViewHolder(View view) { super(view); employeeName = (TextView) view.findViewById(R.id.employeeName); employeeId = (TextView) view.findViewById(R.id.employeeId); } }
@Override public void onBindViewHolder(CustomViewHolder holder, int position) { Employee employee = mEmployeeList.get(position); holder.employeeName.setText(employee.getEmployeeName()); holder.employeeId.setText(String.valueOf(employee.getEmployeeId())); } @Override public int getItemCount() { return mEmployeeList.size(); }
@Override public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_item, parent, false); return new CustomViewHolder(view); } }
The
Employee.java class which contains the data specific to this application are
given below :
package com.androidjavapoint.recyclerviewexample; public class Employee { private String employeeName; private int employeeId; public Employee(String employeeName, int employeeId) { this.employeeName = employeeName; this.employeeId = employeeId; } public String getEmployeeName() { return employeeName; } public int getEmployeeId() { return employeeId; } }
At
the end of this post I hope you gained the knowledge about Android
RecyclerView.
To
find more interesting topics on Software development follow me at https://medium.com/@ankit.sinhal
You
can also find my Android Applications on play store
Comments
Post a Comment