TrinityTuts

Implement load more on RecyclerView Android

Last updated on January 5th, 2020 at 09:17 pm

In this post I am going to explain to you how we can implement load more on scroll load in recycler view Android application. Load more work like this “((visibleItemCount + pastVisibleItems) >= totaltemCount)” when we scroll our recycler view and we reach to end then we load more data. To learn this I can explain it in the simple step below.

Load more data on scroll RecyclerView

Step 1. Create a new Android project in Android studio.

Step 2. Once the project created add required library for this project, I am using Okhttp 3 and Glide library to load data from API and show an image using the Glide library.

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    implementation 'com.android.support:recyclerview-v7:28.0.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation("com.squareup.okhttp3:okhttp:4.2.1")
    implementation 'com.github.bumptech.glide:glide:4.8.0'
}

Step 3. Now once library sync successfully we need to add Internet permission to load API from the server. Open AndroidManifest.xml and add internet permission in it.

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

Step 4. Now create a new layout file (user_list.xml) which we use in the recycler view.

<?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="wrap_content"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="10dp">

        <ImageView
            android:id="@+id/image"
            android:layout_width="44dp"
            android:layout_height="44dp" />

        <TextView
            android:id="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:text="" />
    </LinearLayout>
</LinearLayout>

Step 5. After layout creates two package adapter and model. Adapter set data in view and Model hold data that we get from API.

UserListAdapter

package com.scrollmorerecyclerview.adapter;

import android.app.Activity;
import android.content.Context;
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.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.RequestOptions;
import com.scrollmorerecyclerview.R;
import com.scrollmorerecyclerview.model.UserModel;

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

public class UserListAdapter extends RecyclerView.Adapter<UserListAdapter.CustomViewHolder> {

    private List<UserModel> imageModelsList;
    private Context mContext;
    private Activity act;

    public UserListAdapter(Context context, ArrayList<UserModel> imageList, Activity activity) {
        this.imageModelsList = imageList;
        this.mContext = context;
        this.act = activity;
    }

    @Override
    public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(this.mContext).inflate(R.layout.user_list, parent, false);
        CustomViewHolder viewHolder = new CustomViewHolder(view);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(CustomViewHolder holder, final int position) {
        final UserModel get = imageModelsList.get(position);

        holder.name.setText(get.getName());
        final String image = get.getImage();

        RequestOptions options = new RequestOptions();
        Glide
                .with(this.mContext)
                .load(image)
                .apply(new RequestOptions().transforms(new CenterCrop(), new RoundedCorners(10)))
                .into(holder.image);

        holder.name.setText(get.getName());

    }


    @Override
    public int getItemCount() {
        return (null != imageModelsList ? imageModelsList.size() : 0);
    }


    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public int getItemViewType(int position) {
        return position;
    }

    class CustomViewHolder extends RecyclerView.ViewHolder {

        ImageView image;
        TextView name;

        public CustomViewHolder(View itemView) {
            super(itemView);
            image = (ImageView) itemView.findViewById(R.id.image);
            name = (TextView) itemView.findViewById(R.id.name);
        }
    }
}

UserModel

package com.scrollmorerecyclerview.model;

public class UserModel {
    int id;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getImage() {
        return image;
    }

    public void setImage(String image) {
        this.image = image;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    String image, name;
}

Step 6. Now we open activity_main.xml file and add RecyclerView in it.

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>

</android.support.constraint.ConstraintLayout>

Step 7. Now open your MainActivity.java file and in this, we load data from API and set in RecyclerView. I create a simple function through which we call API. For this post, I am using reqres.in you can use there API it’s free and easy to use.

public void getUserList(){
    Request request = new Request.Builder()
            .url("https://reqres.in/api/users?per_page=15&page=1")
            .header("Accept", "application/json")
            .header("Content-Type", "application/json")
            .build();

    client.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            String mMessage = e.getMessage().toString();
            Log.w("failure Response", mMessage);
            call.cancel();
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {

            final String mMessage = response.body().string();

            MainActivity.this.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    try {
                        JSONObject response = new JSONObject(mMessage);
                        JSONArray users = response.getJSONArray("data");

                        for (int i = 0; i < users.length(); i++){
                            JSONObject user = users.getJSONObject(i);

                            UserModel userModel = new UserModel();
                            userModel.setName(user.getString("first_name"));
                            userModel.setImage(user.getString("avatar"));

                            userModelArrayList.add(userModel);
                        }

                        userListAdapter.notifyDataSetChanged();
                        loading = false;

                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    });
}

Now call this method inside onCreate. I already find RecyclerView and already initialize adapter, you will get complete code at the bottom.

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


    list = (RecyclerView)findViewById(R.id.list);
    linearLayoutManager = new LinearLayoutManager(getApplicationContext());
    list.setLayoutManager(linearLayoutManager);
    userModelArrayList = new ArrayList<>();

    userListAdapter = new UserListAdapter(this, userModelArrayList, this);
    list.setAdapter(userListAdapter);

    getUserList();
}

Now our code load data from API and display in View. Now if you want to add a load more in RecyclerView we need to add addOnScrollListener to load more data on a scroll as shown in below code

list.addOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        if (dy > 0)
        {
            visibleItemCount = linearLayoutManager.getChildCount();
            totalItemCount = linearLayoutManager.getItemCount();
            pastVisibleItems = linearLayoutManager.findFirstVisibleItemPosition();

            if (!loading) {
                if ((visibleItemCount + pastVisibleItems) >= totalItemCount) {
                    loading = true;
                    //page = page+1;
                    getUserList();
                }
            }
        }
    }
});

I am using the same function to load data again on scroll load you pass your parameter to load actual data. Here is complete code of MainActivity.java

package com.scrollmorerecyclerview;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;

import com.scrollmorerecyclerview.adapter.UserListAdapter;
import com.scrollmorerecyclerview.model.UserModel;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.ArrayList;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class MainActivity extends AppCompatActivity {

    RecyclerView list;

    ArrayList<UserModel> userModelArrayList;
    UserListAdapter userListAdapter;
    LinearLayoutManager linearLayoutManager;
    int page = 1;
    OkHttpClient client = new OkHttpClient();
    int pastVisibleItems, visibleItemCount, totalItemCount;
    Boolean loading = true;

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


        list = (RecyclerView)findViewById(R.id.list);
        linearLayoutManager = new LinearLayoutManager(getApplicationContext());
        list.setLayoutManager(linearLayoutManager);
        userModelArrayList = new ArrayList<>();

        userListAdapter = new UserListAdapter(this, userModelArrayList, this);
        list.setAdapter(userListAdapter);

        list.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                if (dy > 0)
                {
                    visibleItemCount = linearLayoutManager.getChildCount();
                    totalItemCount = linearLayoutManager.getItemCount();
                    pastVisibleItems = linearLayoutManager.findFirstVisibleItemPosition();

                    if (!loading) {
                        if ((visibleItemCount + pastVisibleItems) >= totalItemCount) {
                            loading = true;
                            //page = page+1;
                            getUserList();
                        }
                    }
                }
            }
        });

        getUserList();
    }

    public void getUserList(){
        Request request = new Request.Builder()
                .url("https://reqres.in/api/users?per_page=15&page=1")
                .header("Accept", "application/json")
                .header("Content-Type", "application/json")
                .build();

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                String mMessage = e.getMessage().toString();
                Log.w("failure Response", mMessage);
                call.cancel();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {

                final String mMessage = response.body().string();

                MainActivity.this.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            JSONObject response = new JSONObject(mMessage);
                            JSONArray users = response.getJSONArray("data");

                            for (int i = 0; i < users.length(); i++){
                                JSONObject user = users.getJSONObject(i);

                                UserModel userModel = new UserModel();
                                userModel.setName(user.getString("first_name"));
                                userModel.setImage(user.getString("avatar"));

                                userModelArrayList.add(userModel);
                            }

                            userListAdapter.notifyDataSetChanged();
                            loading = false;

                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
        });
    }
}

You can download the complete code from the below link.

https://github.com/anehkumar/scroll-load-more-data-on-recyclerview