9

I have a RecyclerView that im trying to implement an infinite scroll feature into. The issue is, the code inside the if statements in the OnScrolled method is being executed twice. Heres my current code:

public abstract class InfiniteScroll extends RecyclerView.OnScrollListener {

private LinearLayoutManager mLayoutManager;
private int previousTotal = 0;
private boolean loading = true;
private int visibleThreshold = 5;
int firstVisibleItem, visibleItemCount, totalItemCount;

private int current_page = 1;

public InfiniteScroll(LinearLayoutManager layoutManager) {
    mLayoutManager = layoutManager;
}

@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

    visibleItemCount = recyclerView.getChildCount();
    totalItemCount = mLayoutManager.getItemCount();
    firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();

    if (loading) {
        if (totalItemCount > previousTotal) {
            loading = false;
            previousTotal = totalItemCount;
        }
    }
    if (!loading && (totalItemCount - visibleItemCount)
            <= (firstVisibleItem + visibleThreshold)) {
        // End has been reached

        // Do something
        current_page++;
        Log.d("moreitems", "why is this being called twice?");
        loadMore(current_page);

        loading = true;
    }
}

public abstract void loadMore(int current_page);
}

This code was posted as an answer to a separate SO question, and other examples seem to function similar, but I still get the loadMore() method executing twice when reaching the bottom of the RecyclerView, and im not sure why.

Orbit
  • 2,694
  • 7
  • 40
  • 80

4 Answers4

13

it's getting called because when you loadMore items, onScrolled is called again.

This callback will also be called if visible item range changes after a layout calculation. In that case, dx and dy will be 0.

so you could check if (!loading && dy>0) as well

Sameer J
  • 226
  • 3
  • 13
  • 4
    Btw, I've added it to the start of `onScrolled` so nothing will be executed, is there a reason you used it with the `!loading`?, I saw it can go with `!loading` as well but why to execute in-between code, is it ok I moved it upwards like: `if(dy <= 0) return;`, I mean I didn't saw any problem with my code but maybe you run into some rare cases? – Aviel Fedida Oct 13 '16 at 17:36
0

Try this:

 public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
                totalItemCount = linearLayoutManager.getItemCount();
                lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
                if (!loading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
                    loading = true;
                    // End has been reached
                    // Do something
                       current_page++;
                       Log.d("moreitems", "why is this being called twice?");
                       loadMore(current_page);

                }
            }
Sabari
  • 1,853
  • 1
  • 11
  • 10
  • Where do you set loading back to `false` with this solution? Otherwise loading stays `true` and reaching the end of the list again wont trigger another load. – Orbit Feb 09 '16 at 22:27
  • I have posted a sample code here :http://stackoverflow.com/questions/35253695/recyclerview-load-more-with-progressbar-error/35254285#35254285 – Sabari Feb 10 '16 at 01:32
  • Add loading = false; in the loarmore() method (last line). You should make loading to false after all you stuffs were completed. – Sabari Feb 10 '16 at 01:38
-1

I just met similar situation, while solution is quite different from the above answer.

In my case, I have a custom RecyclerViewFragment, which will set up RecyclerView at the beginning of data loading stuff. And I add a custom OnScrollListener at that set up method block.

My reason why OnScrollListener was called twice is, I accidently add two OnScrollListener to my RecyclerView. Thus these two listener will both listener to the "scroll to the end" action and do something for it.

So I just remove all the OnScrollListener for my RecyclerView before I call the set up method, to make sure that there will only be one OnScrollListener.

Hope this help.

Anthonyeef
  • 2,067
  • 24
  • 21
-2
if (layoutManager.findLastCompletelyVisibleItemPosition() == 
recyclerAdapter.getItemCount() - 1) {
     //load more items code is here
}

This will work.

GvSharma
  • 2,302
  • 22
  • 29