Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
[Android] Endless load more for RecyclerView
public abstract class EndlessRecyclerScrollListener extends RecyclerView.OnScrollListener {
// The minimum amount of items to have below your current scroll position
// before loading more.
private int visibleThreshold = 5;
// The current offset index of data you have loaded
private int currentPage = 0;
// The total number of items in the dataset after the last load
private int previousTotalItemCount = 0;
// True if we are still waiting for the last set of data to load.
private boolean loading = true;
// Sets the starting page index
private int startingPageIndex = 0;
private RecyclerView.LayoutManager layoutManager;
// private final FragmentArticleList fragmentArticleList;
public void setLayoutManager(RecyclerView.LayoutManager layoutManager) {
this.layoutManager = layoutManager;
public RecyclerView.LayoutManager getLayoutManager() {
return layoutManager;
public EndlessRecyclerScrollListener(LinearLayoutManager layoutManager) {
this.layoutManager = layoutManager;
private int getLastVisibleItem(int[] lastVisibleItemPositions) {
int maxSize = 0;
for (int i = 0; i < lastVisibleItemPositions.length; i++) {
if (i == 0) {
maxSize = lastVisibleItemPositions[i];
} else if (lastVisibleItemPositions[i] > maxSize) {
maxSize = lastVisibleItemPositions[i];
return maxSize;
// This happens many times a second during a scroll, so be wary of the code you place here.
// We are given a few useful parameters to help us work out if we need to load some more data,
// but first we check if we are waiting for the previous load to finish.
public void onScrolled(RecyclerView view, int dx, int dy) {
if (dy < 1) {
// don't do anything when scrolling up.
int lastVisibleItemPosition = 0;
int totalItemCount = layoutManager.getItemCount();
if (layoutManager instanceof StaggeredGridLayoutManager) {
int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) layoutManager).findLastVisibleItemPositions(null);
// get maximum element within the list
lastVisibleItemPosition = getLastVisibleItem(lastVisibleItemPositions);
} else if (layoutManager instanceof GridLayoutManager) {
lastVisibleItemPosition = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition();
} else if (layoutManager instanceof LinearLayoutManager) {
lastVisibleItemPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
// If the total item count is zero and the previous isn't, assume the
// list is invalidated and should be reset back to initial state
if (totalItemCount < previousTotalItemCount) {
this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = totalItemCount;
if (totalItemCount == 0) {
this.loading = true;
// If it’s still loading, we check to see if the dataset count has
// changed, if so we conclude it has finished loading and update the current page
// number and total item count.
if (loading && (totalItemCount >= previousTotalItemCount)) {
loading = false;
previousTotalItemCount = totalItemCount;
// If it isn’t currently loading, we check to see if we have reached
// the visibleThreshold and need to reload more data.
// If we do need to reload some more data, we execute onLoadMore to fetch the data.
// threshold should reflect how many total columns there are too
if (!loading && (lastVisibleItemPosition + visibleThreshold) > totalItemCount) {
onLoadMore(currentPage, totalItemCount, view);
loading = true;
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
// supply a positive number to recyclerView.canScrollVertically(int direction) to check if scrolling down.
boolean canScrollDownMore = recyclerView.canScrollVertically(1);
// If recyclerView.canScrollVertically(1) returns false it means you're at the end of the list.
if (!canScrollDownMore) {
onScrolled(recyclerView, 0, 1);
// Call this method whenever performing new searches on in onRefresh() if using SwipeRefresh
public void resetState() {
this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = 0;
this.loading = true;
// Defines the process for actually loading more data based on page
public abstract void onLoadMore(int page, int totalItemsCount, RecyclerView view);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.