// Tutorial //

Android RecyclerView Load More, Endless Scrolling

Published on August 3, 2022
Default avatar
By Anupam Chugh
Developer and author at DigitalOcean.
Android RecyclerView Load More, Endless Scrolling

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

In this tutorial, we’ll be discussing and implementing Endless Scrolling or Infinite Scroll on RecyclerView in our Android Application. The infinite scrolling in which the next set of rows are fetched from the DB/Server while showing a loading icon is commonly seen in many applications such as Facebook, Twitter. It’s recommended to go through this tutorial before proceeding ahead.

Android RecyclerView Load More

In order to show Loading icon at the bottom of RecyclerView while the next set of items are fetched, we need to use Multiple View Types in our RecyclerView Adapter. How is this implemented? Typically in a simple RecyclerView, we load elements to the adapter from a Data Structure. In order to show the loading icon view at the bottom of the RecyclerView, we need to first add a NULL element to the end of the Data Structure. Why NULL? In order to differentiate that element from the rest of the elements and show a different view type row. After adding a null, we notify the adapter the of the new element and fetch the next set of elements. Once the next set of elements is obtained, we remove the NULL element and add the next set to the bottom of the Data Structure. Following diagram demonstrates what actually happens in the RecyclerView and its Adapter. android recyclerview loadmore flow

In order to detect that the user has scrolled to the end of the RecyclerView, we need to implement OnScrollListener() on the RecyclerView.

Enough Talk. Let’s code. In the following section, we’ll demonstrate Endless Scrolling on RecyclerView by populating a List of Strings and loading the next set of List after a delay using Handlers.

Project Structure

android recyclerview load more project structure


The code for the activity_main.xml layout is given below:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="https://schemas.android.com/apk/res/android"

        app:layout_constraintTop_toTopOf="parent" />


The layout for the rows of the RecyclerView is defined in item_row.xml file as shown below:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="https://schemas.android.com/apk/res/android"

        android:text="Item X" />


The layout for the loading view is defined in the item_loading.xml file as shown below:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"



The code for the RecyclerViewAdapter.java class is given below:

package com.journaldev.androidrecyclerviewloadmore;

import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;

import java.util.List;

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private final int VIEW_TYPE_ITEM = 0;
    private final int VIEW_TYPE_LOADING = 1;

    public List<String> mItemList;

    public RecyclerViewAdapter(List<String> itemList) {

        mItemList = itemList;

    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        if (viewType == VIEW_TYPE_ITEM) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_row, parent, false);
            return new ItemViewHolder(view);
        } else {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_loading, parent, false);
            return new LoadingViewHolder(view);

    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {

        if (viewHolder instanceof ItemViewHolder) {

            populateItemRows((ItemViewHolder) viewHolder, position);
        } else if (viewHolder instanceof LoadingViewHolder) {
            showLoadingView((LoadingViewHolder) viewHolder, position);


    public int getItemCount() {
        return mItemList == null ? 0 : mItemList.size();

     * The following method decides the type of ViewHolder to display in the RecyclerView
     * @param position
     * @return
    public int getItemViewType(int position) {
        return mItemList.get(position) == null ? VIEW_TYPE_LOADING : VIEW_TYPE_ITEM;

    private class ItemViewHolder extends RecyclerView.ViewHolder {

        TextView tvItem;

        public ItemViewHolder(@NonNull View itemView) {

            tvItem = itemView.findViewById(R.id.tvItem);

    private class LoadingViewHolder extends RecyclerView.ViewHolder {

        ProgressBar progressBar;

        public LoadingViewHolder(@NonNull View itemView) {
            progressBar = itemView.findViewById(R.id.progressBar);

    private void showLoadingView(LoadingViewHolder viewHolder, int position) {
        //ProgressBar would be displayed


    private void populateItemRows(ItemViewHolder viewHolder, int position) {

        String item = mItemList.get(position);



getItemViewType is where we check each element of the List. If the element is NULL we set the view type as 1 else 0. Based on the View type we instantiate the ViewHolder in the onCreateViewHolder. Inside the onBindViewHolder we check the type of ViewHolder instance and populate the row accordingly. Let’s look at the MainActivity.java class where we instantiate the above Adapter.

package com.journaldev.androidrecyclerviewloadmore;

import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    RecyclerView recyclerView;
    RecyclerViewAdapter recyclerViewAdapter;
    ArrayList<String> rowsArrayList = new ArrayList<>();

    boolean isLoading = false;

    protected void onCreate(Bundle savedInstanceState) {

        recyclerView = findViewById(R.id.recyclerView);


    private void populateData() {
        int i = 0;
        while (i < 10) {
            rowsArrayList.add("Item " + i);

    private void initAdapter() {

        recyclerViewAdapter = new RecyclerViewAdapter(rowsArrayList);

    private void initScrollListener() {
        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);

            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

                LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();

                if (!isLoading) {
                    if (linearLayoutManager != null && linearLayoutManager.findLastCompletelyVisibleItemPosition() == rowsArrayList.size() - 1) {
                        //bottom of list!
                        isLoading = true;


    private void loadMore() {
        recyclerViewAdapter.notifyItemInserted(rowsArrayList.size() - 1);

        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            public void run() {
                rowsArrayList.remove(rowsArrayList.size() - 1);
                int scrollPosition = rowsArrayList.size();
                int currentSize = scrollPosition;
                int nextLimit = currentSize + 10;

                while (currentSize - 1 < nextLimit) {
                    rowsArrayList.add("Item " + currentSize);

                isLoading = false;
        }, 2000);


initScrollListener is the most important method in the above code. It’s there where we check the scrolled state of the RecyclerView and if the bottom-most item is visible we show the loading view and populate the next list. The output of the above application in action is given below: That brings an end to this tutorial. You can download the project from the link below:


Github Project Link

If you’ve enjoyed this tutorial and our broader community, consider checking out our DigitalOcean products which can also help you achieve your development goals.

Learn more here

About the authors
Default avatar
Developer and author at DigitalOcean.

Still looking for an answer?

Was this helpful?

Thanks a lot, it’s working and great decision.

- Eugene

    Simple and easy to go through.

    - devraj singh

      HI, I am using volley, and when requesting data, I am consulting 5 items, but the recycler only shows 4, why is this error?

      - Paul

        why the linearLayoutManager.findLastCompletelyVisibleItemPosition() equals with -1 ?

        - mahdi

          How to pupulateData() from Model Arraylist ?

          - Redigo

            I stopped reading at this line: <android.support.v7.widget.RecyclerView android:id=“@+id/recyclerView” android:layout_width=“match_parent” android:layout_height=“wrap_content” <- will trigger lot of drawings

            - duna

              nice example. It gives me an error saying “cannot call this method in a scroll callback” but it is fixed by calling recyclerView.post() method. Just a note.

              - Numan

                What if I use grid layout manager and I want the load more to Cover full length?

                - Carlos

                  All Code is Good it worked also…But use for loop instead of while loop because app is getting struck when we break the while loop with condition and in my real time also after some time app is freezed… Just use for loop instead of while in whole code then it will be a excellent tutorial example…

                  - Krishna Kamesh

                    Can you make this article in kotlin version?

                    - Ade Fajar