Android

Android RecyclerView Load More Endless Scrolling

Pinterest LinkedIn Tumblr

In this tutorial, we’re going to implement Endless scrolling via RecyclerView. Why do we need endless scrolling? This is the question which we’re going to solve in this tutorial.

Many apps display so much data in form of a list. This data cannot be load at the same time. It takes time to load and sometimes if you’re loading data Via Rest APIs, then a timeout error occurred.

To solve this problem, we implement endless scrolling. For example, we can load data after 10 records or 20 records. We can set addOnScrollListener on RecyclerView to load more data because it provides the onScrolled() method which we can use to load more data according to our logic.

Tutorial Contents

  1. Step -1 (Create a new project)
  2. Step-2 (Gradle file)
  3. Step-3 (Project Colors.xml file)
  4. Step-4 (design a layout file for RecyclerView Item)
  5. Step-5 (Create the drawable resouces for row layout)
  6. Step-6 (Working with modal class)
  7. Step- 7 (Working with RecyclerView Adapter Java file)
  8. Step-8 (Working with activity_main.xml file)
  9. Step-9 (Working with MainActivity.java file)

Demo

Step -1 (Create a new project)

Open the Android Studio tool and create a new project with a blank template.

Step-2 (Gradle file)

Make sure, the project Gradle file has below dependencies

    implementation 'androidx.appcompat:appcompat:1.3.0'
    implementation 'com.google.android.material:material:1.3.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

Step-3 (Project Colors.xml file)

Open the colors.xml file and add the below code to it.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="purple_200">#FFBB86FC</color>
    <color name="purple_500">#FF6200EE</color>
    <color name="purple_700">#FF3700B3</color>
    <color name="teal_200">#FF03DAC5</color>
    <color name="teal_700">#FF018786</color>
    <color name="black">#FF000000</color>
    <color name="white">#FFFFFFFF</color>

    <!-- view colors -->
    <color name="red_view">#C70E0E</color>
    <color name="green_view">#015F25</color>
    <color name="blue_view">#1126CB</color>
    <color name="purple_view">#7109A8</color>
</resources>

Step-4 (design a layout file for RecyclerView Item)

Navigate to the app > res > layout > Right-click on it > New >Layout Resource File and renamed it adapter_demo.xml. Add below code to it.

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    app:cardUseCompatPadding="true"
    android:layout_height="100dp">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <View
            android:id="@+id/viewBg"
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:background="@drawable/view_with_red_color"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/tvNumber"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="1"
            android:textColor="@color/white"
            android:textSize="24sp"
            android:textStyle="bold"
            app:layout_constraintBottom_toBottomOf="@+id/viewBg"
            app:layout_constraintEnd_toEndOf="@+id/viewBg"
            app:layout_constraintStart_toStartOf="@+id/viewBg"
            app:layout_constraintTop_toTopOf="@+id/viewBg" />

        <TextView
            android:id="@+id/tvTitle"
            android:layout_width="0dp"
            android:layout_marginStart="5dp"
            android:layout_height="wrap_content"
            android:text="@string/random_title"
            android:textColor="@color/black"
            android:textSize="20sp"
            app:layout_constraintVertical_chainStyle="packed"
            app:layout_constraintBottom_toTopOf="@+id/tvDescription"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/viewBg"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/tvDescription"
            android:layout_width="0dp"
            android:layout_marginStart="5dp"
            android:layout_height="wrap_content"
            android:text="@string/random_description"
            android:textColor="@color/black"
            android:textSize="16sp"
            android:lines="3"
            android:ellipsize="end"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/viewBg"
            app:layout_constraintTop_toBottomOf="@+id/tvTitle" />


    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>

Step-5 (Create the drawable resouces for row layout)

In adapter_demo.xml, four resource files being used for different colorful circles. Create the four drawable layouts same like adapter_demo.xml file, navigate to the app > res > drawable > Right-click on it> New > Drawable Resource File

1- Blue color Circle (Drawable)

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
    <solid android:color="@color/blue_view"/>
</shape> 

2- Green Color Circle (Drawable)

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
    <solid android:color="@color/green_view"/>
</shape>

3- Purple Color Circle (Drawable)

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
    <solid android:color="@color/purple_view"/>
</shape>

4- Red Color Circle (Drawable)

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
    <solid android:color="@color/red_view"/>
</shape>

Step-6 (Working with modal class)

Create a Java file and renamed it with RandomM.java. Add the below code to it

package com.example.recyclerviewloadmore;

public class RandomM {
    private String title;
    private String description;
    private int type = 0; // 0 for display item and 1 for loading bar

    public RandomM(String title, String description, int type) {
        this.title = title;
        this.description = description;
        this.type = type;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }
}

Step- 7 (Working with RecyclerView Adapter Java file)

Create a new Java class and renamed it with AdapterRandom.java. If you have no idea, how to create a RecyclerView Adapter class? Read this tutorial first. Add the below code to it

package com.example.recyclerviewloadmore;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.List;

public class AdapterRandom extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private List<RandomM> randomMList;
    private int[] bgDrawables = {R.drawable.view_with_red_color, R.drawable.view_with_blue_color, R.drawable.view_with_purple_color, R.drawable.view_with_green_color};
    private Context _context;


    AdapterRandom(List<RandomM> randomMList) {
        this.randomMList = randomMList;
    }

    private class RandomViewHolder extends RecyclerView.ViewHolder {
        private TextView tvTitle;
        private TextView tvNumber;
        private TextView tvDescription;
        private View viewBg;

        public RandomViewHolder(View itemView) {
            super(itemView);
            tvTitle = itemView.findViewById(R.id.tvTitle);
            tvNumber = itemView.findViewById(R.id.tvNumber);
            tvDescription = itemView.findViewById(R.id.tvDescription);
            viewBg = itemView.findViewById(R.id.viewBg);
        }
    }

    private class ProgressBarViewHolder extends RecyclerView.ViewHolder {
        private ProgressBar progressBar;

        public ProgressBarViewHolder(View itemView) {
            super(itemView);
            progressBar = itemView.findViewById(R.id.progressLoadingBar);
        }
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        _context = parent.getContext();
        if (viewType == 1) {
            View v1 = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_loading_more, parent, false);
            return new ProgressBarViewHolder(v1);
        } else {
            View v1 = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_demo, parent, false);
            return new RandomViewHolder(v1);
        }
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        if (holder.getItemViewType() == 0) {
            RandomViewHolder randomViewHolder = (RandomViewHolder) holder;
            RandomM celebrityModal = randomMList.get(position);
            randomViewHolder.tvTitle.setText(celebrityModal.getTitle());
            randomViewHolder.tvDescription.setText(celebrityModal.getDescription());
            randomViewHolder.viewBg.setBackgroundResource(bgDrawables[position % 4]);
            randomViewHolder.tvNumber.setText((position + 1) + "");
        }
    }

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

    @Override
    public int getItemViewType(int position) {
        return randomMList.get(position).getType();
    }
}

Step-8 (Working with activity_main.xml file)

Open the activity_main.xml file from the layout folder and add the below code to it.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tvDemoTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="@string/demo_title"
        android:textColor="@color/black"
        android:textSize="26sp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rcvListing"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_margin="10dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tvDemoTitle" />

</androidx.constraintlayout.widget.ConstraintLayout>

Step-9 (Working with MainActivity.java file)

Go to the MainActivity.java file and add the below code to it. Comments are added inside the code to understand the code. Code comments are helpful, if you don’t understand do the comment below.

package com.example.recyclerviewloadmore;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.os.Bundle;
import android.os.Handler;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private RecyclerView rcvListing;
    private AdapterRandom adapterRandom;
    private List<RandomM> randomMList;
    private boolean isLoading = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initComponents();
        prepareDummyData();
        initOnScrollListener();
    }

    /**
     * initialize the components
     */
    private void initComponents() {
        randomMList = new ArrayList<>();
        adapterRandom = new AdapterRandom(randomMList);
        rcvListing = findViewById(R.id.rcvListing);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        linearLayoutManager.setOrientation(RecyclerView.VERTICAL);
        rcvListing.setLayoutManager(linearLayoutManager);
        rcvListing.setAdapter(adapterRandom);
    }

    /**
     * setup the dummy data to random list and recall the adapter
     */
    private void prepareDummyData() {
        for (int i = 0; i < 10; i++) {
            randomMList.add(new RandomM(getString(R.string.random_title), getString(R.string.random_description), 0));
        }
        adapterRandom.notifyDataSetChanged();
    }

    private void initOnScrollListener() {
        // set the add on scroll listener to recyclerview
        rcvListing.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
            }

            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();

                // if loading process already is not in progress
                if (!isLoading) {
                    if (linearLayoutManager != null && (linearLayoutManager.findLastCompletelyVisibleItemPosition() == randomMList.size() - 1)) {
                        loadMoreData();
                        isLoading = true;
                    }
                }
            }
        });
    }

    /**
     * when scroll will reach at last item of RecyclerView, then this method will call and will load more 10 items
     */
    private void loadMoreData() {
        // add header type in recyclerview and notify to the adapter
        randomMList.add(new RandomM(null, null, 1));
        adapterRandom.notifyItemInserted(randomMList.size());
        Handler handler = new Handler();

        // this handler will call after 2.5 second and will add 10 items in the list.
        handler.postDelayed(() -> {
            randomMList.remove(randomMList.size() - 1);
            adapterRandom.notifyItemRemoved(randomMList.size());
            for (int i = 0; i < 10; i++) {
                randomMList.add(new RandomM(getString(R.string.random_title), getString(R.string.random_description), 0));
            }
            adapterRandom.notifyDataSetChanged();
            isLoading = false;
        }, 2500);
    }

}

Thanks for reading the tutorial. Subscribe to my YouTube channel. Like and Share my Facebook page with your friends.

Write A Comment