Open In App

How to Implement Pagination in Android RecyclerView using Volley?

Last Updated : 26 Feb, 2021
Improve
Improve
Like Article
Like
Save
Share
Report

Pagination is one of the most important factors which helps to reduce the loading time inside our app and increase the performance of our data which is represented in the form of Lists. In this article, we will take a look at adding pagination in our Android RecyclerView. And to get the data from API we are going to use the Volley library. 

What is Pagination?

Pagination is to load data according to requirement rather than loading complete data at a time. So this helps to reduce the loading time for our data from our API as well as increase the performance of our application. 

What is the benefit of using Pagination in your lists of data? 

Many times there is a situation when we have to load a huge amount of the data at a time in our list view or recycler view. So if we load all the data at a time it will take some time to load the data and this will increase the loading time of our Recycler View. Pagination will provide you support with the help of it we can load data in the form of chunks so this will prevent our recycler view from degrading its performance and loading of the data will be faster.

What we are going to build in this article? 

We will be building a simple application in which we will be displaying a list of data in our Android RecyclerView and we will be adding pagination in our RecyclerView to load our data. A sample video is given below to get an idea about what we are going to do in this article. Note that we are going to implement this project using the Java language. 

Step by Step Implementation

Step 1: Create a New Project

To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio. Note that select Java as the programming language.

Step 2: Add the below dependency in your build.gradle file

Below is the dependency for Volley which we will be using to get the data from API. For adding this dependency navigate to the app > Gradle Scripts > build.gradle(app) and add the below dependency in the dependencies section. We have used the Picasso dependency for image loading from the URL.   

// below dependency for using picasso image loading library and volley

implementation ‘com.squareup.picasso:picasso:2.71828’

implementation ‘com.android.volley:volley:1.1.1’

After adding this dependency sync your project and now move towards the AndroidManifest.xml part.  

Step 3: Adding permissions to the internet in the AndroidManifest.xml file

Navigate to the app > AndroidManifest.xml and add the below code to it. 

XML




<uses-permission android:name="android.permission.INTERNET" />


Step 4: Working with the activity_main.xml file

Navigate to the app > res > layout > activity_main.xml and add the below code to that file. Below is the code for the activity_main.xml file. 

XML




<?xml version="1.0" encoding="utf-8"?>
<!--in this we are displaying a nested scroll view-->
<androidx.core.widget.NestedScrollView 
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/idNestedSV"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
  
    <!--linear layout for displaying
        our recycler view-->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
          
        <!--recycler view for displaying our list of data
            and we are making nested scroll for our 
            recycler view as false-->
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/idRVUsers"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:nestedScrollingEnabled="false"
            tools:listitem="@layout/user_rv_item" />
          
        <!--we are adding progress bar
            for the purpose of loading-->
        <ProgressBar
            android:id="@+id/idPBLoading"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>
      
</androidx.core.widget.NestedScrollView>


Step 5: Creating a Modal class for storing our data

For storing our data we have to create a new java class. For creating a new java class, Navigate to the app > java > your app’s package name > Right-click on it > New > Java class and name it as UserModal and add the below code to it. Comments are added inside the code to understand the code in more detail.

Java




public class UserModal {
    // variables for our first name, 
    // last name, email and avatar
    private String first_name;
    private String last_name;
    private String email;
    private String avatar;
  
    public String getFirst_name() {
        return first_name;
    }
  
    public void setFirst_name(String first_name) {
        this.first_name = first_name;
    }
  
    public String getLast_name() {
        return last_name;
    }
  
    public void setLast_name(String last_name) {
        this.last_name = last_name;
    }
  
    public String getEmail() {
        return email;
    }
  
    public void setEmail(String email) {
        this.email = email;
    }
  
    public String getAvatar() {
        return avatar;
    }
  
    public void setAvatar(String avatar) {
        this.avatar = avatar;
    }
  
    public UserModal(String first_name, String last_name, String email, String avatar) {
        this.first_name = first_name;
        this.last_name = last_name;
        this.email = email;
        this.avatar = avatar;
    }
}


Step 6: Creating a layout file for each item of our RecyclerView

Navigate to the app > res > layout > Right-click on it > New > layout resource file and give the file name as user_rv_item and add the below code to it. Comments are added in the code to get to know in more detail. 

XML




<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView 
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:elevation="8dp"
    app:cardCornerRadius="8dp">
  
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="2dp">
  
        <!--image view for displaying user image-->
        <ImageView
            android:id="@+id/idIVUser"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_margin="10dp" />
  
        <!--text view for displaying first name-->
        <TextView
            android:id="@+id/idTVFirstName"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:layout_toEndOf="@id/idIVUser"
            android:layout_toRightOf="@id/idIVUser"
            android:text="First Name"
            android:textColor="@color/black"
            android:textSize="15sp" />
  
        <!--text view for displaying last name-->
        <TextView
            android:id="@+id/idTVLastName"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/idTVFirstName"
            android:layout_marginTop="10dp"
            android:layout_toEndOf="@id/idIVUser"
            android:layout_toRightOf="@id/idIVUser"
            android:text="Last Name"
            android:textColor="@color/black"
            android:textSize="15sp" />
  
        <!--text view for displaying user email-->
        <TextView
            android:id="@+id/idTVEmail"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/idTVLastName"
            android:layout_marginTop="10dp"
            android:layout_toEndOf="@id/idIVUser"
            android:layout_toRightOf="@id/idIVUser"
            android:text="Email"
            android:textColor="@color/black"
            android:textSize="15sp" />
  
    </RelativeLayout>
  
</androidx.cardview.widget.CardView>


Step 7: Creating an Adapter class for setting data to our RecyclerView item

For creating a new Adapter class navigate to the app > java > your app’s package name > Right-click on it > New > Java class and name it as UserRVAdapter and add the below code to it. 

Java




import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
  
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
  
import com.squareup.picasso.Picasso;
  
import java.util.ArrayList;
  
public class UserRVAdapter extends RecyclerView.Adapter<UserRVAdapter.ViewHolder> {
     
    // variable for our array list and context.
    private ArrayList<UserModal> userModalArrayList;
    private Context context;
  
    // creating a constructor.
    public UserRVAdapter(ArrayList<UserModal> userModalArrayList, Context context) {
        this.userModalArrayList = userModalArrayList;
        this.context = context;
    }
  
    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        // inflating our layout file on below line.
        View view = LayoutInflater.from(context).inflate(R.layout.user_rv_item, parent, false);
        return new ViewHolder(view);
    }
  
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
          
        // getting data from our array list in our modal class.
        UserModal userModal = userModalArrayList.get(position);
          
        // on below line we are setting data to our text view.
        holder.firstNameTV.setText(userModal.getFirst_name());
        holder.lastNameTV.setText(userModal.getLast_name());
        holder.emailTV.setText(userModal.getEmail());
          
        // on below line we are loading our image 
        // from url in our image view using picasso.
        Picasso.get().load(userModal.getAvatar()).into(holder.userIV);
    }
  
    @Override
    public int getItemCount() {
        // returning the size of array list.
        return userModalArrayList.size();
    }
  
    public class ViewHolder extends RecyclerView.ViewHolder {
        // creating a variable for our text view and image view.
        private TextView firstNameTV, lastNameTV, emailTV;
        private ImageView userIV;
  
        public ViewHolder(@NonNull View itemView) {
            super(itemView);
              
            // initializing our variables.
            firstNameTV = itemView.findViewById(R.id.idTVFirstName);
            lastNameTV = itemView.findViewById(R.id.idTVLastName);
            emailTV = itemView.findViewById(R.id.idTVEmail);
            userIV = itemView.findViewById(R.id.idIVUser);
        }
    }
}


Step 8: Working with the MainActivity.java file

Go to the MainActivity.java file and refer to the following code. Below is the code for the MainActivity.java file. Comments are added inside the code to understand the code in more detail.

Java




import android.os.Bundle;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast;
  
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.widget.NestedScrollView;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
  
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
  
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
  
import java.util.ArrayList;
  
public class MainActivity extends AppCompatActivity {
  
    // creating a variable for our array list, adapter class,
    // recycler view, progressbar, nested scroll view
    private ArrayList<UserModal> userModalArrayList;
    private UserRVAdapter userRVAdapter;
    private RecyclerView userRV;
    private ProgressBar loadingPB;
    private NestedScrollView nestedSV;
      
    // creating a variable for our page and limit as 2
    // as our api is having highest limit as 2 so 
    // we are setting a limit = 2
    int page = 0, limit = 2;
  
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
         
        // creating a new array list.
        userModalArrayList = new ArrayList<>();
          
        // initializing our views.
        userRV = findViewById(R.id.idRVUsers);
        loadingPB = findViewById(R.id.idPBLoading);
        nestedSV = findViewById(R.id.idNestedSV);
          
        // calling a method to load our api.
        getDataFromAPI(page, limit);
          
        // adding on scroll change listener method for our nested scroll view.
        nestedSV.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {
            @Override
            public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
                // on scroll change we are checking when users scroll as bottom.
                if (scrollY == v.getChildAt(0).getMeasuredHeight() - v.getMeasuredHeight()) {
                    // in this method we are incrementing page number,
                    // making progress bar visible and calling get data method.
                    page++;
                    loadingPB.setVisibility(View.VISIBLE);
                    getDataFromAPI(page, limit);
                }
            }
        });
    }
  
    private void getDataFromAPI(int page, int limit) {
        if (page > limit) {
            // checking if the page number is greater than limit.
            // displaying toast message in this case when page>limit.
            Toast.makeText(this, "That's all the data..", Toast.LENGTH_SHORT).show();
              
            // hiding our progress bar.
            loadingPB.setVisibility(View.GONE);
            return;
        }
        // creating a string variable for url .
        String url = "https://reqres.in/api/users?page=" + page;
          
        // creating a new variable for our request queue
        RequestQueue queue = Volley.newRequestQueue(MainActivity.this);
          
        // creating a variable for our json object request and passing our url to it.
        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                try {
                      
                    // on below line we are extracting data from our json array.
                    JSONArray dataArray = response.getJSONArray("data");
                      
                    // passing data from our json array in our array list.
                    for (int i = 0; i < dataArray.length(); i++) {
                        JSONObject jsonObject = dataArray.getJSONObject(i);
                          
                        // on below line we are extracting data from our json object.
                        userModalArrayList.add(new UserModal(jsonObject.getString("first_name"), jsonObject.getString("last_name"), jsonObject.getString("email"), jsonObject.getString("avatar")));
                          
                        // passing array list to our adapter class.
                        userRVAdapter = new UserRVAdapter(userModalArrayList, MainActivity.this);
                          
                        // setting layout manager to our recycler view.
                        userRV.setLayoutManager(new LinearLayoutManager(MainActivity.this));
                          
                        // setting adapter to our recycler view.
                        userRV.setAdapter(userRVAdapter);
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                // handling on error listener method.
                Toast.makeText(MainActivity.this, "Fail to get data..", Toast.LENGTH_SHORT).show();
            }
        });
        // calling a request queue method 
        // and passing our json object
        queue.add(jsonObjectRequest);
    }
}


Now run your app and see the output of the app. 

Output:



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads