2

Recyclerview comes with its own scroll listener which has the following methods :

void onScrollStateChanged(RecyclerView recyclerView, int newState)

Callback method to be invoked when RecyclerView's scroll state changes.

void onScrolled(RecyclerView recyclerView, int dx, int dy)

Callback method to be invoked when the RecyclerView has been scrolled.

Is there any way to trigger loader to load more data when scroll reaches end of the list?

I have implemented this way:

@Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
    GenerItem generItem=generItems.get(i);
    Log.d("TAG","position "+i);
    if(i==generItems.size()-1)
    ((GenerSearchActivity)mContext).onScroll(i);
    viewHolder.bindValues(generItem);
}

Here onScroll() in Activity, will trigger the loader to load more data. What is the best way please suggest.

Rohit Singh
  • 11,804
  • 4
  • 65
  • 66
RQube
  • 854
  • 2
  • 11
  • 27

2 Answers2

1

Make Next Call at the end of scroll

enter image description here

There are essentially 3 steps.

  1. Notify when the list is scrolled
  2. Make REST call (for NEXT page)
  3. Add the result in the old list + Notify DataSet change

CALLBACK

But first, we need a Callback which would work as a bridge between RecyclerView.Adapter and Activity

public interface PaginationCallBack{
     public void oadNextPage();
}

Implement this callback in Your Activity

class YourActivity extends AppCompatActivity implements PaginationCallBack{

     int pageNum = 1;

     @Override
     public void loadNextPage(){
           // Your implementation
     }
}

Initialize Callback in RecyclerView.Adapter

class YourAdapter extends RecyclerView.Adapter{

     private PaginationCallBack paginationCallBack;

     public YourAdapter(PaginationCallBack paginationCallBack) {
        this.paginationCallBack = paginationCallBack;
     }

}

STEP 1 Add a condition in onBindViewHolder method and notify with a Callback.

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewholder, int position) {

    if(position+1==images.size()){
        paginationCallBack.loadNextPage();  // Callback
    }

}

Step 2: Call NEXT Page

getImages(++pageNum) // YOUR REST method which page number

@Override
public void loadNextPage(){
    getImages(++pageNumber) // REST call with next Page 
}

Step 3 Add the result in old list and notify datasetChanged

public void getImages(int pageNum){

      List<Images> newResults = //RESTCALL
      imageList.addAll(newResults);
      adapter.updateDataSet(imageList)

}

Where is updateDataSet(imageList) method?

Write this method inside RecyclerView.Adapter

 public void updateDataSet(List<GalleryMedia> newImages){

    if(newImages!=null){
        images = newImages;
    }

    notifyDataSetChanged();
}

Full Code

RecyclerView Pagination

Result:

enter image description here

Rohit Singh
  • 11,804
  • 4
  • 65
  • 66
0

Here's a scroll listener which implements load more and quick return pattern:

public abstract class HidingScrollListener extends RecyclerView.OnScrollListener {

    private static final float  HIDE_THRESHOLD   = 10;
    private static final float  SHOW_THRESHOLD   = 70;

    private int                 mToolbarOffset   = 0;
    private boolean             mControlsVisible = true;
    private int                 mToolbarHeight;
    private int                 mTotalScrolledDistance;
    private int                 previousTotal    = 0;
    private boolean             loading          = true;
    private int                 visibleThreshold = 4;
    int                         firstVisibleItem, visibleItemCount, totalItemCount;
    private LinearLayoutManager layoutManager;

    public HidingScrollListener(Context context, LinearLayoutManager layoutManager) {
        mToolbarHeight = Tools.getFooterHeight(context);
        this.layoutManager = layoutManager;
    }

    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);

        if (newState == RecyclerView.SCROLL_STATE_IDLE) {
            if (mTotalScrolledDistance < mToolbarHeight) {
                setVisible();
            }
            else {
                if (mControlsVisible) {
                    if (mToolbarOffset > HIDE_THRESHOLD) {
                        setInvisible();
                    }
                    else {
                        setVisible();
                    }
                }
                else {
                    if ((mToolbarHeight - mToolbarOffset) > SHOW_THRESHOLD) {
                        setVisible();
                    }
                    else {
                        setInvisible();
                    }
                }
            }
        }

    }

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

        clipToolbarOffset();
        onMoved(mToolbarOffset);

        if ((mToolbarOffset < mToolbarHeight && dy > 0) || (mToolbarOffset > 0 && dy < 0)) {
            mToolbarOffset += dy;
        }
        if (mTotalScrolledDistance < 0) {
            mTotalScrolledDistance = 0;
        }
        else {
            mTotalScrolledDistance += dy;
        }
        // for load more
        visibleItemCount = recyclerView.getChildCount();
        totalItemCount = layoutManager.getItemCount();
        firstVisibleItem = layoutManager.findFirstVisibleItemPosition();

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

            loading = true;
            onLoadMore();
        }
    }

    private void clipToolbarOffset() {
        if (mToolbarOffset > mToolbarHeight) {
            mToolbarOffset = mToolbarHeight;
        }
        else if (mToolbarOffset < 0) {
            mToolbarOffset = 0;
        }
    }

    private void setVisible() {
        if (mToolbarOffset > 0) {
            onShow();
            mToolbarOffset = 0;
        }
        mControlsVisible = true;
    }

    private void setInvisible() {
        if (mToolbarOffset < mToolbarHeight) {
            onHide();
            mToolbarOffset = mToolbarHeight;
        }
        mControlsVisible = false;
    }

    public abstract void onMoved(int distance);

    public abstract void onShow();

    public abstract void onHide();

    public abstract void onLoadMore();
}

And it's implementation is below:

HidingScrollListener scrollListener = new HidingScrollListener(activity, manager) {
         @Override
         public void onMoved(int distance) {

         }

         @Override
         public void onShow() {

         }

         @Override
         public void onHide() {

         }

         @Override
         public void onLoadMore() {
            // you can do your pagination here.
         }
      };
      mRecyclerView.addOnScrollListener(scrollListener);
savepopulation
  • 10,674
  • 4
  • 47
  • 68