Created
December 24, 2018 04:25
-
-
Save anitaa1990/0e8911211faef2dd374cd8f750053704 to your computer and use it in GitHub Desktop.
An alternate to Android Paging Library - to enable Pagination in RecyclerView
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public abstract class RecyclerViewPaginator extends RecyclerView.OnScrollListener { | |
/* | |
* This is the Page Limit for each request | |
* i.e. every request will fetch 19 transactions | |
* */ | |
private Long batchSize = 19l; | |
/* | |
* Variable to keep track of the current page | |
* */ | |
private Long currentPage = 0l; | |
/* | |
* This variable is used to set | |
* the threshold. For instance, if I have | |
* set the page limit to 20, this will notify | |
* the app to fetch more transactions when the | |
* user scrolls to the 18th item of the list. | |
* */ | |
private Integer threshold = 2; | |
/* | |
* This is a hack to ensure that the app is notified | |
* only once to fetch more data. Since we use | |
* scrollListener, there is a possibility that the | |
* app will be notified more than once when user is | |
* scrolling. This means there is a chance that the | |
* same data will be fetched from the backend again. | |
* This variable is to ensure that this does NOT | |
* happen. | |
* */ | |
private boolean endWithAuto = false; | |
/* | |
* We pass the RecyclerView to the constructor | |
* of this class to get the LayoutManager | |
* */ | |
private RecyclerView.LayoutManager layoutManager; | |
public RecyclerViewPaginator(RecyclerView recyclerView) { | |
recyclerView.addOnScrollListener(this); | |
this.layoutManager = recyclerView.getLayoutManager(); | |
} | |
@Override | |
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { | |
super.onScrollStateChanged(recyclerView, newState); | |
if(newState == SCROLL_STATE_IDLE) { | |
int visibleItemCount = layoutManager.getChildCount(); | |
int totalItemCount = layoutManager.getItemCount(); | |
int firstVisibleItemPosition = 0; | |
if(layoutManager instanceof LinearLayoutManager) { | |
firstVisibleItemPosition = ((LinearLayoutManager)layoutManager).findLastVisibleItemPosition(); | |
} else if(layoutManager instanceof GridLayoutManager) { | |
firstVisibleItemPosition = ((GridLayoutManager)layoutManager).findLastVisibleItemPosition(); | |
} | |
//if(isLoading()) return | |
if(isLastPage()) return; | |
if ((visibleItemCount + firstVisibleItemPosition + threshold) >= totalItemCount) { | |
if(!endWithAuto) { | |
endWithAuto = true; | |
loadMore(getStartSize(), getMaxSize()); | |
} | |
} else { | |
endWithAuto = false; | |
} | |
} | |
} | |
public Long getStartSize() { | |
return ++currentPage; | |
} | |
public Long getMaxSize() { | |
return currentPage + batchSize; | |
} | |
/* | |
* I have added a reset method here | |
* that can be called from the UI because | |
* if we have a filter option in the app, | |
* we might need to refresh the whole data set | |
* */ | |
public void reset() { | |
currentPage = 0l; | |
} | |
@Override | |
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { | |
super.onScrolled(recyclerView, dx, dy); | |
} | |
/* | |
* I have created two abstract methods: | |
* isLastPage() where the UI can specify if | |
* this is the last page - this data usually comes from the backend. | |
* | |
* loadMore() where the UI can specify to load | |
* more data when this method is called. | |
* | |
* We can also specify another method called | |
* isLoading() - to let the UI display a loading View. | |
* Since I did not need to display this, I have | |
* commented it out. | |
* */ | |
//public abstract boolean isLoading(); | |
public abstract boolean isLastPage(); | |
public abstract void loadMore(Long start , Long count); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment