BIW BIW - 1 year ago 115
Android Question

onLoadMoreListener won't stop loading - RecyclerView - Android

I have a user feed where user's posts will be displayed if the current user is following them, at the moment I have the

working fine in regards to it loading the next batch of images when they get to the bottom of the
. But, when I reach the last item (the feeds only shows 50 posts) in the List it'll attempt to load more and cause an
. I've restricted the size of the list in the adapter, but at the minute I can't seem to work out when the user has hit the very bottom to stop the progress from displaying and to stop the OnLoadMoreListener from triggering. This is what I have tried so far:

Adapter Constructor:

public RecyclerViewAdapterAllFeeds(Context context,
final ArrayList<AllFeedsDataModel> previousPostsList, final boolean profile, RecyclerView recyclerView, final ProgressBar progressBar) {
this.context = context;
this.previousPostsList = previousPostsList;
this.profile = profile;
if(recyclerView.getLayoutManager() instanceof LinearLayoutManager){
final LinearLayoutManager linearLayoutManager = (LinearLayoutManager)recyclerView.getLayoutManager();
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (getItemCount() > LOADED_POSTS - 2) {
totalItemCount = getItemCount();
// total_posts = getItemCount();
lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
if (lastVisibleItem <= TOTAL_POSTS) {
if (!loading && totalItemCount <= (lastVisibleItem)) {
if (onLoadMoreListener != null) {
loading = true;


adapter = new RecyclerViewAdapterAllFeeds(getActivity(), latestUpdatesList, false, recyclerView, progressBar);
recyclerView.setAdapter(adapter);// set adapter on recyclerview
adapter.setOnLoadMoreListener(new RecyclerViewAdapterAllFeeds.OnLoadMoreListener() {
public void onLoadMore() {
populateRecyclerView(true, refreshCount);
adapter.notifyDataSetChanged();// Notify the adapter

My question is how can I stop it loading if the total posts is less than that of the restrictions or to know when the final item is visible?

Answer Source

First create


public abstract class EndlessRecyclerViewScrollListener 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;

    RecyclerView.LayoutManager mLayoutManager;

    public EndlessRecyclerViewScrollListener(LinearLayoutManager layoutManager) {
        this.mLayoutManager = layoutManager;

    public EndlessRecyclerViewScrollListener(GridLayoutManager layoutManager) {
        this.mLayoutManager = layoutManager;
        visibleThreshold = visibleThreshold * layoutManager.getSpanCount();

    public EndlessRecyclerViewScrollListener(StaggeredGridLayoutManager layoutManager) {
        this.mLayoutManager = layoutManager;
        visibleThreshold = visibleThreshold * layoutManager.getSpanCount();

    public 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) {
        int lastVisibleItemPosition = 0;
        int totalItemCount = mLayoutManager.getItemCount();

        if (mLayoutManager instanceof StaggeredGridLayoutManager) {
            int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(null);
            // get maximum element within the list
            lastVisibleItemPosition = getLastVisibleItem(lastVisibleItemPositions);
        } else if (mLayoutManager instanceof LinearLayoutManager) {
            lastVisibleItemPosition = ((LinearLayoutManager) mLayoutManager).findLastVisibleItemPosition();
        } else if (mLayoutManager instanceof GridLayoutManager) {
            lastVisibleItemPosition = ((GridLayoutManager) mLayoutManager).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 breached
        // 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);
            loading = true;

    // Defines the process for actually loading more data based on page
    public abstract void onLoadMore(int page, int totalItemsCount);


And then implement in this way:

recyclerView.addOnScrollListener(new EndlessRecyclerViewScrollListener(recyclerView.getLayoutManager()) {
            public void onLoadMore(int page, int totalItemsCount) {

                //TODO Add logic for load more posts or show message if posts is ended.