Android | RecyclerView Using Support Library ListAdapter

Less than 100 pages covering Kotlin syntax and features in straight and to the point explanation.
ListAdapter
for RecyclerView
has been introduced in Revision 27.1.0 Release of Support Library. ListAdapter
uses DiffUtil
under the hood to compute list diffs on a background thread. This will help RecyclerView
animate changes automatically with less work on the UI thread.
Environment, Tools & Library
- Android Studio 3.1.4
- Android Support Library
com.android.support:recyclerview-v7:28.0.0
- Java 1.8+ for Lambda experssions support
Overview
We will build an app that displays a list of hard-coded instances of class Link
in a RecyclerView
. We will use ListAdapter
instead of the usual RecyclerView.Adapter
as shown in a previous post Create a List with RecyclerView. To display items on RecyclerView
you need to the following:
RecyclerView
widget added to the activity layout.- A class extending
DiffUtil.ItemCallback
- A class extending
ListAdapter
. - A class extending
RecyclerView.ViewHolder
. - Layout for RecyclerView items.
Files we need for this app are shown in the image below.
( 1 ) Create new Android Project
Create new android application keep default options. This app is targeting API 19 or later
( 2 ) Add the Support Library
- Add the v7 Support Library to gradle build file
build.gradle
dependencies {
implementation 'com.android.support:recyclerview-v7:28.0.0'
}
( 3 ) Add RecyclerView to Layout
- Add
RecyclerView
to the activity layout.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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/forcast_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
( 4 ) Extend DiffUtil.ItemCallback
DiffUtil
is a utility class that can calculate the difference between two lists and output a list of update operations that converts the first list into the second one.DiffUtil.Callback
is a Callback class used byDiffUtil
while calculating the diff between two lists.DiffUtil.Callback
serves two roles - list indexing, and item diffing.ItemCallback
handles just the second of these, which allows separation of code that indexes into an array or List from the presentation-layer and content specific diffing code.
- We need an instance of
DiffUtil.ItemCallback
to be passed intoListAdapter
constructor.
ListAdapter(ItemCallback
diffCallback)
LinkDiffCallback.java
package com.hmkcode.utils;
import android.support.v7.util.DiffUtil;
import com.hmkcode.models.Link;
public class LinkDiffCallback extends DiffUtil.ItemCallback<Link> {
@Override
public boolean areItemsTheSame(Link oldItem, Link newItem) {
return oldItem.getUrl().equals(newItem.getUrl());
}
@Override
public boolean areContentsTheSame(Link oldItem, Link newItem) {
return oldItem.getUrl().equals(newItem.getUrl());
}
}
( 5 ) Functional Interface
This interface is not needed for the implementation of the RecyclerView
. It just serves as a bridge in passing click event from ListAdapter
to MainActivity
to update the list of links List<Link> links;
.
It is annotated with @FunctionalInterface
to take advantage of lambda expression.
package com.hmkcode.listeners;
import com.hmkcode.models.Link;
@FunctionalInterface
public interface MyItemClickListener {
public void onClick(Link link);
}
( 6 ) Extending ListAdapter & RecyclerView.ViewHolder
MyListAdapter
calss extendsListAdapter<Link, MyListAdapter.MyViewHolder>
- Define constructor
MyListAdapter(ItemCallback, MyItemClickListener)
- Override onCreateViewHolder() to inflate layout item_layout & return object of type
MyViewHolder
. - Override onBindViewHolder() to bind returned
MyViewHolder
with item i.e.Link
returned by getItem(position) . - Define inner class
MyViewHolder
that extendsRecyclerView.ViewHolder
package com.hmkcode.adapters;
import android.support.annotation.NonNull;
import android.support.v7.recyclerview.extensions.ListAdapter;
import android.support.v7.util.DiffUtil;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.hmkcode.R;
import com.hmkcode.listeners.MyItemClickListener;
import com.hmkcode.models.Link;
public class MyListAdapter extends ListAdapter<Link, MyListAdapter.MyViewHolder> {
MyItemClickListener myItemClickListener;
public MyListAdapter(@NonNull DiffUtil.ItemCallback diffCallback,
MyItemClickListener myItemClickListener) {
super(diffCallback);
this.myItemClickListener = myItemClickListener;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemLayoutView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_layout, null);
return new MyViewHolder(itemLayoutView);
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder myViewHolder, int position) {
myViewHolder.bind(getItem(position));
}
// inner class
public class MyViewHolder extends RecyclerView.ViewHolder {
private View itemLayoutView;
private TextView itemTitle;
private TextView itemUrl;
private ImageView itemIcon;
public MyViewHolder(View itemLayoutView) {
super(itemLayoutView);
this.itemLayoutView = itemLayoutView;
this.itemTitle = itemLayoutView.findViewById(R.id.item_title);
this.itemUrl = itemLayoutView.findViewById(R.id.item_url);
this.itemIcon = itemLayoutView.findViewById(R.id.item_icon);
}
public void bind(Link link){
this.itemIcon.setImageResource(link.getIcon());
this.itemTitle.setText(link.getTitle());
this.itemUrl.setText(link.getUrl());
this.itemLayoutView.setOnClickListener(
v -> myItemClickListener.onClick(link));
}
}
}
( 7 ) MainActivity
- Obtain a handle to the
RecycleView
object - Set layout manager using setLayoutManager()
You can use a standard layout managers (such as LinearLayoutManager or GridLayoutManager), or implement your own.
- Create an adapter of type
MyListAdapter
listAdapter = new MyListAdapter(new LinkDiffCallback(), link -> updateList(link));
First argument is instance of
LinkDiffCallback
Second argument is lambda expression which is a cooler way of passing argument of typeMyItemClickListener
. You can use anonymous class to accomplish the same result.
- Attach an adapter for the data to be displayed setAdapter(listAdapter).
- Call
listAdapter.submitList(getListData());
MainActivity.java
package com.hmkcode.activities;
import ...
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private List<Link> links;
private ListAdapter listAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recyclerView);
// layout manager
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setClickable(true);
// list adapter
links = getListData();
listAdapter = new MyListAdapter(new LinkDiffCallback(),
link -> updateList(link));
recyclerView.setAdapter(listAdapter);
listAdapter.submitList(getListData());
}
private void updateList(Link link){
boolean removed = links.remove(link);
listAdapter.submitList(new LinkedList(links));
}
//generate a list of Link
private List<Link> getListData(){...}
}
Source Code @ GitHub

Less than 100 pages covering Kotlin syntax and features in straight and to the point explanation.