I have implemented the pagination in recyclerview you can check the example on git hub https://github.com/kunal-mahajan/GitRepositoryList
You wont reload the data again and again by using following code.
Step 1: Create class DynamicLoadingAdapter
import android.content.Context;
import android.graphics.Typeface;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public abstract class DynamicLoadingAdapter extends RecyclerView.Adapter<ViewHolder> {
private static final int ITEM = 3;
private static final int LOADING = 4;
private static final int NO_DATA = 5;
protected List records;
protected Context context;
private LoadingObj loadingObj = new LoadingObj();
private NoDataAvailableObj noDataAvailableObj = new NoDataAvailableObj();
public DynamicLoadingAdapter(Context context) {
this.context = context;
records = new ArrayList<>();
records.add(loadingObj);
}
private int getIntToDP(int px) {
return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, px, context.getResources().getDisplayMetrics()));
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ViewHolder viewHolder = null;
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
switch (viewType) {
case ITEM:
viewHolder = getViewHolder(parent, inflater);
break;
case LOADING:
viewHolder = new DynamicLoadingAdapter.LoadingVH(getProgressBar());
break;
case NO_DATA:
viewHolder = new ViewHolder(getNoDataTextView()) {
};
}
return viewHolder;
}
protected abstract String getEmptyText();
@NonNull
protected abstract ViewHolder getViewHolder(ViewGroup parent, LayoutInflater inflater);
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
if (getItemViewType(position) == ITEM)
setValuesOnBind(holder, position);
}
protected abstract void setValuesOnBind(ViewHolder holder, int position);
@Override
public int getItemViewType(int position) {
Object o = records.get(position);
if (o instanceof LoadingObj)
return LOADING;
if (o instanceof NoDataAvailableObj)
return NO_DATA;
return ITEM;
}
void setLoadingFinished() {
records.remove(records.size() - 1);
if (records.size() == 0) records.add(new NoDataAvailableObj());
notifyDataSetChanged();
}
@Override
public int getItemCount() {
return records.size();
}
int getItemLoadedCount() {
int l = records.size();
if (records.get(records.size() - 1).equals(loadingObj))
l--;
if (l > 0 && records.get(0).equals(noDataAvailableObj))
l--;
return l;
}
void add(List list) {
for (int i = 0; i < list.size(); i++) {
records.add(records.size() - 1, list.get(i));
}
notifyDataSetChanged();
}
private ProgressBar getProgressBar() {
ProgressBar progressBar = new ProgressBar(context);
int h = getIntToDP(30);
int w = ViewGroup.LayoutParams.MATCH_PARENT;
LinearLayout.LayoutParams progressParams = new LinearLayout.LayoutParams(w, h);
int margin = getIntToDP(5);
progressParams.setMargins(margin, margin, margin, margin);
progressParams.gravity = Gravity.CENTER;
progressBar.setLayoutParams(progressParams);
return progressBar;
}
public TextView getNoDataTextView() {
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
TextView textView = new TextView(context);
textView.setGravity(Gravity.CENTER);
textView.setText(getEmptyText());
textView.setTypeface(null, Typeface.ITALIC);
params.setMargins(0, getIntToDP(7), 0, getIntToDP(7));
textView.setLayoutParams(params);
return textView;
}
private static class LoadingObj {
}
private class LoadingVH extends ViewHolder {
public LoadingVH(View itemView) {
super(itemView);
}
}
private class NoDataAvailableObj {
}
}
Step 2: Create class: DynamicLoadingListHelper
import android.content.Context;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import java.util.List;
/**
* Created by Kunal.Mahajan on 7/23/2018.
*/
public abstract class DynamicLoadingListHelper {
private final DynamicLoadingAdapter adapter;
private final Context context;
private LinearLayout containerLayout;
private RecyclerView rv;
private int totalRecords = -1;
private int pageCount = 0;
public DynamicLoadingListHelper(Context context, LinearLayout containerLayout, DynamicLoadingAdapter adapter) {
this.adapter = adapter;
this.context = context;
this.containerLayout = containerLayout;
init();
}
public void init() {
final LinearLayoutManager lm = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false);
rv = new RecyclerView(context);
rv.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
containerLayout.addView(rv);
rv.setLayoutManager(lm);
rv.setItemAnimator(new DefaultItemAnimator());
rv.setAdapter(adapter);
rv.addOnScrollListener(new RecyclerView.OnScrollListener() {
int lastLoadCountReq = Integer.MIN_VALUE;
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (lm.findLastVisibleItemPosition() == adapter.getItemCount() - 1 && newState == RecyclerView.SCROLL_STATE_IDLE && adapter.getItemLoadedCount() < totalRecords && adapter.getItemLoadedCount() > lastLoadCountReq) {
lastLoadCountReq = adapter.getItemLoadedCount();
loadNextPage();
}
}
});
rv.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() {
LinearLayoutManager layoutManager = (LinearLayoutManager) rv.getLayoutManager();
@Override
public void onChildViewAttachedToWindow(View view) {
boolean isScrolled = layoutManager.findViewByPosition(0) != layoutManager.findViewByPosition(layoutManager.findFirstCompletelyVisibleItemPosition());
if (isScrolled)
return;
if (!(view instanceof ProgressBar))
return;
if (isRecyclerScrollable()) {
loadNextPage();
}
}
public void onChildViewDetachedFromWindow(View view) {
}
});
loadNextPage();
}
private void loadNextPage() {
pageCount++;
loadData(pageCount);
}
private boolean isRecyclerScrollable() {
LinearLayoutManager layoutManager = (LinearLayoutManager) rv.getLayoutManager();
RecyclerView.Adapter adapter = rv.getAdapter();
if (layoutManager == null || adapter == null) return false;
return layoutManager.findLastCompletelyVisibleItemPosition() < totalRecords;
}
protected abstract void loadData(int offset);
public void dataLoaded(List list, int totalPage) {
if (totalPage <= 0) {
adapter.setLoadingFinished();
return;
}
this.totalRecords = totalPage;
adapter.add(list);
if (adapter.getItemLoadedCount() >= totalPage)
adapter.setLoadingFinished();
}
}
Step 3:
Create your own PaginationAdaptor eg:
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
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.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.gitfeaturelisting.R;
import com.gitfeaturelisting.component.DynamicLoadingAdapter;
import com.gitfeaturelisting.pojo.Item;
import com.squareup.picasso.Picasso;
/**
* Created by Kunal.Mahajan on 7/23/2018.
*/
public class RepoPaginationAdaptor extends DynamicLoadingAdapter {
public RepoPaginationAdaptor(Context applicationContext) {
super(applicationContext);
}
@Override
protected String getEmptyText() {
return "No repo available";
}
@NonNull
@Override
protected RecyclerView.ViewHolder getViewHolder(ViewGroup parent, LayoutInflater inflater) {
View v = inflater.inflate(R.layout.layout_repo_info_short, parent, false);
final RecyclerView.ViewHolder viewHolder = new RepoInfoVH(v);
return viewHolder;
}
@Override
protected void setValuesOnBind(RecyclerView.ViewHolder holder, int position) {
Item r = (Item) records.get(position);
RepoInfoVH rvh = (RepoInfoVH) holder;
rvh.tvName.setText(r.getDescription());
rvh.tvTitle.setText(r.getName());
rvh.tvRate.setText(context.getString(R.string.updated_on) + " " + (r.getUpdatedAt()));
Picasso.get().load(Uri.parse(r.getOwner().getAvatarUrl())).into(rvh.ivPic);
rvh.llMain.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(context, ActivityRepoDetail.class);
Item r = (Item) records.get(rvh.getLayoutPosition());
i.putExtra(ActivityRepoDetail.KEY_REPO_DETAIL, r);
context.startActivity(i);
}
});
}
private class
RepoInfoVH extends RecyclerView.ViewHolder {
ImageView ivPic;
TextView tvName;
TextView tvTitle;
TextView tvRate;
LinearLayout llMain;
public RepoInfoVH(View jobView) {
super(jobView);
ivPic = jobView.findViewById(R.id.layout_repo_info_short_iv_repo_pic);
tvName = (jobView.findViewById(R.id.layout_repo_info_short_tv_name));
tvTitle = (jobView.findViewById(R.id.layout_repo_info_short_tv_title));
tvRate = (jobView.findViewById(R.id.layout_repo_info_short_tv_bottom));
llMain = (jobView.findViewById(R.id.layout_repo_info_short_ll));
}
}
}