Pagination Recyclerview Android Java We use the Pagination Library of Android Jetpack in this app to fetch data from the database to recyclerView by retrofit API, This code is following the principles of MVVM design pattern and LiveData.
// add dependence of pagination to gradel script
def paging_version = "2.1.2"
implementation "androidx.paging:paging-runtime:$paging_version" // pagination
// add another dependencies [Optional]
implementation 'com.github.bumptech.glide:glide:4.11.0' // For Image
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
def retrofit2_version = "2.8.1" //Retrofit2
implementation "com.squareup.retrofit2:retrofit:$retrofit2_version"
implementation "com.squareup.retrofit2:converter-gson:$retrofit2_version"
def lifecycle_version = "2.2.0" //lifecycle
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
implementation "android.arch.lifecycle:extensions:$lifecycle_version"
annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version"
public abstract class PaginationScrollListener extends RecyclerView.OnScrollListener {
private LinearLayoutManager layoutManager;
public PaginationScrollListener(LinearLayoutManager layoutManager) {
this.layoutManager = layoutManager;
}
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int visibleItemCount = layoutManager.getChildCount();
int totalItemCount = layoutManager.getItemCount();
int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();
if (!isLoading() && !isLastPage()) {
if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount && firstVisibleItemPosition >= 0) {
loadMoreItems();
}
}
}
protected abstract void loadMoreItems();
protected abstract int getTotalPageCount();
protected abstract boolean isLastPage();
protected abstract boolean isLoading();
}
private int pageStart = 1 ;
private Boolean isLoading = false ;
private Boolean isLastPage = false ;
private int totalPages = 1 ;
private int currentPage = pageStart ;
binding.recyclerMyOrders
.addOnScrollListener(new PaginationScrollListener((LinearLayoutManager) binding.recyclerMyOrders.getLayoutManager()) {
@Override
protected void loadMoreItems() {
isLoading = true ;
currentPage += 1 ;
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
loadNextPage();
}
} , 1000);
}
@Override
protected int getTotalPageCount() {
return totalPages;
}
@Override
protected boolean isLastPage() {
return isLastPage;
}
@Override
protected boolean isLoading() {
return isLoading;
}
});
public class AdapterTopMoviesPagination extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements PaginationAdapterCallback {
private HomeActivity mActivity;
private int item = 0 ;
private int loading = 1 ;
private Boolean isLoadingAdded = false;
private Boolean retryPageLoad = false;
private String errorMsg = "";
private List<ResultsItem> moviesModels = new ArrayList();
public AdapterTopMoviesPagination(HomeActivity mActivity) {
this.mActivity = mActivity;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if(viewType == item){
ItemMovieBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.item_movie, parent, false);
return new TopMoviesVH(binding);
}else{
ItemLoadingBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.item_loading, parent, false) ;
return new LoadingVH(binding);
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
ResultsItem model = moviesModels.get(position);
if(getItemViewType(position) == item){
TopMoviesVH myOrderVH = (TopMoviesVH) holder;
myOrderVH.itemRowBinding.movieProgress.setVisibility(View.VISIBLE);
if (model.getReleaseDate() != null){
myOrderVH.bind(model);
}else{
moviesModels.remove(position);
}
}else{
LoadingVH loadingVH = (LoadingVH) holder;
if (retryPageLoad) {
loadingVH.itemRowBinding.loadmoreErrorlayout.setVisibility(View.VISIBLE);
loadingVH.itemRowBinding.loadmoreProgress.setVisibility(View.GONE);
if(errorMsg != null) loadingVH.itemRowBinding.loadmoreErrortxt.setText(errorMsg);
else loadingVH.itemRowBinding.loadmoreErrortxt.setText(mActivity.getString(R.string.error_msg_unknown));
} else {
loadingVH.itemRowBinding.loadmoreErrorlayout.setVisibility(View.GONE);
loadingVH.itemRowBinding.loadmoreProgress.setVisibility(View.VISIBLE);
}
loadingVH.itemRowBinding.loadmoreRetry.setOnClickListener(view -> {
showRetry(false, "");
retryPageLoad();
});
loadingVH.itemRowBinding.loadmoreErrorlayout.setOnClickListener(view -> {
showRetry(false, "");
retryPageLoad();
});
}
}
@Override
public int getItemCount() {
return Math.max(moviesModels.size(), 0);
}
@Override
public int getItemViewType(int position) {
if (position == 0){
return item;
}else {
if (position == moviesModels.size() - 1 && isLoadingAdded) {
return loading;
} else {
return item;
}
}
}
@Override
public void retryPageLoad() {
mActivity.loadNextPage();
}
public static class TopMoviesVH extends RecyclerView.ViewHolder {
ItemMovieBinding itemRowBinding;
public TopMoviesVH(@NonNull ItemMovieBinding binding) {
super(binding.getRoot());
itemRowBinding = binding;
}
void bind(Object obj){
itemRowBinding.setVariable(BR.model, obj);
itemRowBinding.executePendingBindings();
}
}
public static class LoadingVH extends RecyclerView.ViewHolder{
ItemLoadingBinding itemRowBinding;
public LoadingVH(@NonNull ItemLoadingBinding binding) {
super(binding.getRoot());
itemRowBinding = binding;
}
}
public void showRetry( Boolean show, String errorMsg){
retryPageLoad = show ;
notifyItemChanged(moviesModels.size() - 1);
this.errorMsg = errorMsg ;
}
public void add(ResultsItem moive) {
moviesModels.add(moive);
notifyItemInserted(moviesModels.size() - 1);
}
public void addAll(List<ResultsItem> movies) {
for (int i = 0 ; i < movies.size() ; i++){
add(movies.get(i));
}
}
public void addLoadingFooter() {
isLoadingAdded = true;
add(new ResultsItem());
}
public void removeLoadingFooter() {
isLoadingAdded = false;
int position = moviesModels.size() -1 ;
ResultsItem movie = moviesModels.get(position);
if(movie != null){
moviesModels.remove(position);
notifyItemRemoved(position);
}
}
}
Please note that Pagination Library is a well-supported and Free License, so you can use the app and edit.