Android RecyclerView Infinite Scroll Tutorial

In this tutorial, we are going to implement Android RecyclerView infinite scroll. Imagine you have a large data source you plan to load on a RecyclerView adapter, if you bind all the data at once it will certainly affect the smooth scrolling of your app and your app will appear as running slow.

We will implement the concept of android RecyclerView infinite scroll which will load more data into RecyclerView at the end of visible loaded data as we scroll up or down. This way everything works the way they are meant to be.

Before we dive into more details, it is important for us to understand what we are planning to achieve. Below is the screen-shot of the application we will be creating.

recyclerviewinfinitescroll

Lets start to soil our hands in code. Start up your IDE. For this tutorial, I am using the following tools and environment, feel free to use what works for you.

Windows 7

Android Studio

Sony Xperia ZL

Min SDK 14

Target SDK 23

To create a new android application project, follow the steps as stipulated below.

Go to File menu

Click on New menu

Click on Android Application

Enter Project name: AndroidRecyclerViewInfiniteScroll

Package: com.inducesmile.androidrecyclerviewinfinitescroll

Select Blank Activity

Name your activity : MainActivity

Keep other default selections

Continue to click on next button until Finish button is active, then click on Finish Button.

Strings.xml

We are going to update our project strings.xml file located in the values folder inside the res folder. Open the file and add the code below to it.

android:layout_width="match_parent"
<resources>
    <string name="app_name">Android RecyclerView Infinite Scroll</string>
</resources>

Colors.xml

Open the colors.xml file in the same location as the strings.xml file and add the code below to the file.

<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
<color name="colorBlack">#000000</color>
<color name="colorWhite">#ffffff</color>
</resources>

activity_main.xml

Let’s open our project main layout file, we are going to add a RecycerView. Add the code below inside this file.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.inducesmile.androidrecyclerviewinfinitescroll.MainActivity">
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical" />
</RelativeLayout>

Since we are going use a RecyclerView adapter with the RecyclerView object, we will proceed to create the recyclerview item list layout. This is the layout file that each item on the Recyclerview will use to display its data content.

item_list.xml

Go to the res > layout folder and open item_list.xml file in your environment. Add the code below to the file.

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="16dp"
    card_view:cardCornerRadius="4dp"
    card_view:cardUseCompatPadding="true"
    card_view:cardPreventCornerOverlap="true"
    card_view:cardElevation="4dp">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
       <ImageView
           android:id="@+id/icon_image"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:src="@drawable/sideicon"
           android:layout_alignParentLeft="true"
           android:layout_marginLeft="8dp"
           android:layout_marginTop="18dp"
           android:adjustViewBounds="true"
           android:contentDescription="@string/app_name"/>
        <TextView
            android:id="@+id/title_header"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@+id/icon_image"
            android:layout_alignBaseline="@+id/icon_image"
            android:padding="18dp"
            android:text="@string/app_name"/>
    </RelativeLayout>
</android.support.v7.widget.CardView>

progress_item.xml

Go the layout folder, right click and choose create new file. Name the file progress_item.xml. This is will be use when we want to add new data in our RecyclerView. It will tell the user that some new data is beginning load. Open the file and add the code below.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ProgressBar
        android:id="@+id/progressBar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:indeterminate="true"
        style="@android:style/Widget.Holo.ProgressBar"
        android:layout_gravity="center_horizontal"/>
</LinearLayout>

RecyclerViewAdapter.java

Now, we will move over to the RecyclerView adapter which will extends RecyclerView.Adapter<RecyclerViewHolders>. In this class, we are going to override three methods getItemViewType(int position), RecyclerViewHolders onCreateViewHolder(ViewGroup parent, int viewType) and onBindViewHolder(RecyclerViewHolders holder, int position).

In the constructor, we will pass an instance of the RecyclerView as a parameter and add the addOnScrollListener event. We will override the onScrolled method of this inner class and implement the infinite data loading.

Open this file and add the code below to the file.

import android.content.Context;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewHolders> {
    private List<String> itemList;
    protected Context context;
    private int visibleThreshold = 5;
    private int lastVisibleItem, totalItemCount;
    private boolean loading;
    private OnLoadMoreListener onLoadMoreListener;
    public RecyclerViewAdapter(Context context, List<String> itemList, RecyclerView recyclerView) {
        this.itemList = itemList;
        this.context = context;
        if(recyclerView.getLayoutManager() instanceof LinearLayoutManager){
            final LinearLayoutManager linearLayoutManager = (LinearLayoutManager)recyclerView.getLayoutManager();
            recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
                    totalItemCount = linearLayoutManager.getItemCount();
                    lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
                    if(!loading && totalItemCount <= (lastVisibleItem + visibleThreshold)){
                        if(onLoadMoreListener != null){
                            onLoadMoreListener.onLoadMore();
                        }
                        loading = true;
                    }
                }
            });
        }
    }
    @Override
    public int getItemViewType(int position) {
        return itemList.get(position) != null ? 1 : 0;
    }
    @Override
    public RecyclerViewHolders onCreateViewHolder(ViewGroup parent, int viewType) {
        RecyclerViewHolders viewHolder = null;
        if(viewType == 1){
            View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, parent, false);
            viewHolder = new RecyclerViewHolders(layoutView);
        }else{
            View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, parent, false);
            viewHolder = new ProgressViewHolder(layoutView);
        }
        return viewHolder;
    }
    @Override
    public void onBindViewHolder(RecyclerViewHolders holder, int position) {
        if(holder instanceof RecyclerViewHolders){
            ((RecyclerViewHolders)holder).textTitle.setText(itemList.get(position));
        }else{
            ((ProgressViewHolder)holder).progressBar.setIndeterminate(true);
        }
    }
    public void setLoad(){
        loading = false;
    }
    @Override
    public int getItemCount() {
        return this.itemList.size();
    }
    public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener){
        this.onLoadMoreListener = onLoadMoreListener;
    }
    public interface OnLoadMoreListener {
        void onLoadMore();
    }
    public void setLoaded() {
        loading = false;
    }
}

If you remember, we create two layout files for our adapter class, one for the item list and the other for the progressbar. Since we will use the View Holder pattern in the adapter, we will create two different classes that will extends from the RecyclerView.Holder class.

RecyclerViewHolders.java

Go to your project package folder, right click and choose create a new file. Name the file RecyclerViewHolders.java. Open this file and paste the code below inside this file.

import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
public class RecyclerViewHolders extends RecyclerView.ViewHolder implements View.OnClickListener{
    public ImageView displayedImage;
    public TextView textTitle;
    public RecyclerViewHolders(View itemView) {
        super(itemView);
        itemView.setOnClickListener(this);
        textTitle = (TextView)itemView.findViewById(R.id.title_header);
    }
    @Override
    public void onClick(View view) {
    }
}

ProgressViewHolder.java

We will follow the same procedure as above to create this file. Once you have created it, open the file and paste the code below inside the file.

import android.view.View;
import android.widget.ProgressBar;
public class ProgressViewHolder extends RecyclerViewHolders{
    public ProgressBar progressBar;
    public ProgressViewHolder(View itemView) {
        super(itemView);
        progressBar = (ProgressBar)itemView.findViewById(R.id.progressBar);
    }
}

MainActivity

Finally, we will go to our MainActivity.java file. This is the activity file that will make use of the main layout file we added a RecyclerView to.

We will get the instance of the RecyclerView, set a LinearLayourManager object to it. In the setAdapter method of the class , we will pass an instance of the RecyclerView Adapter we created.

Open this file and add the below code inside the file.

import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
    private static final String TAG = MainActivity.class.getSimpleName();
    private RecyclerView recyclerView;
    private RecyclerViewAdapter recyclerViewAdapter;
    private LinearLayoutManager linearLayoutManager;
    private  List<String> adapterData;
    private Handler handler;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        handler = new Handler();
        linearLayoutManager = new LinearLayoutManager(MainActivity.this);
        // return the data object
        adapterData = getFirstData();
        recyclerView = (RecyclerView)findViewById(R.id.recycler_view);
        recyclerView.setLayoutManager(linearLayoutManager);
        recyclerViewAdapter = new RecyclerViewAdapter(MainActivity.this, adapterData, recyclerView);
        recyclerView.setAdapter(recyclerViewAdapter);
        recyclerViewAdapter.setOnLoadMoreListener(new RecyclerViewAdapter.OnLoadMoreListener() {
            @Override
            public void onLoadMore() {
                adapterData.add(null);
                recyclerViewAdapter.notifyItemInserted(adapterData.size() - 1);
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        adapterData.remove(adapterData.size() - 1);
                        recyclerViewAdapter.notifyItemRemoved(adapterData.size());
                        for (int i = 0; i < 15; i++) {
                            adapterData.add("Item" + (adapterData.size() + 1));
                            recyclerViewAdapter.notifyItemInserted(adapterData.size());
                        }
                        recyclerViewAdapter.setLoaded();
                    }
                }, 2000);
                System.out.println("load");
            }
        });
    }
    private List<String> getFirstData(){
        List<String> listObject = new ArrayList<String>();
        listObject.add("one");
        listObject.add("one");
        listObject.add("one");
        listObject.add("one");
        listObject.add("one");
        listObject.add("one");
        listObject.add("one");
        listObject.add("one");
        listObject.add("one");
        listObject.add("one");
        return listObject;
    }
}

This brings us to the end of this tutorial. I hope that you have learn something. The next tutorial will be on Android RecyclerView Infinite Scroll.

You can download the code for this tutorial below. If you are having hard time downloading the tutorials, kindly contact me.

Remember to subscribe with your email address so that you will be among the first to receive my new android blog post once it is published.

Please if you love this tutorial, kindly download my android app – Complete Mathematics – in Google Play Store and let me know what you think about it.

OTHER INTERESTING POSTS:

4 Comments

    • Henry

Add a Comment