Y.S. Y.S. - 1 month ago 39
Android Question

Endless RecyclerView with ProgressBar for pagination

I am using a

and fetching objects from an API in batches of ten. For pagination, I use
EndlessRecyclerOnScrollListener
.

It's all working properly. Now all that's left is to add a progress spinner at the bottom of the list while the next batch of objects is fetched by the API. Here is a screenshot of the Google Play Store app, showing a
ProgressBar
in what is surely a
RecyclerView
:

enter image description here

The problem is, neither the
RecyclerView
nor the
EndlessRecyclerOnScrollListener
have built-in support for showing a
ProgressBar
at the bottom while the next batch of objects is being fetched.

I have already seen the following answers:

1. Put an indeterminate
ProgressBar
as footer in a
RecyclerView
grid
.

2. Adding items to Endless Scroll
RecyclerView
with
ProgressBar
at bottom
.

I am not satisfied with those answers (both by the same person). This involves shoehorning a
null
object into the data-set midway while the user is scrolling and then taking it out after the next batch is delivered. It looks like a hack that sidesteps the main problem which may or may not work properly. And it causes a bit of jarring and distortion in the list

Using
SwipeRefreshLayout
is not a solution here.
SwipeRefreshLayout
involves pulling from the top to fetch the newest items, and it does not show a progress view anyway.

Can someone please provide a good solution for this? I am interested in knowing how Google has implemented this for their own apps (the Gmail app has it too). Are there any articles where this is shown in detail? All answers & comments will be appreciated. Thank you.

Some other references:

1. Pagination with
RecyclerView
. (Superb overview ...)

2.
RecyclerView
header and footer
. (More of the same ...)

3. Endless
RecyclerView
with
ProgressBar
at bottom
.

Answer

I implemented this on my old project, I did it as follows...

I've created an interface as the guys of your examples did

public interface LoadMoreItems {
  void LoadItems();
}

Then I add added an addOnScrollListener() on my Adapter

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

                totalItemCount = linearLayoutManager.getItemCount();
                lastVisibleItem = linearLayoutManager
                        .findLastVisibleItemPosition();
                if (!loading
                        && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
                    //End of the items
                    if (onLoadMoreListener != null) {
                        onLoadMoreListener.LoadItems();
                    }
                    loading = true;

                }
            }
        });

The onCreateViewHolder() is where I put the ProgressBar or not.

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                  int viewType) {
    RecyclerView.ViewHolder vh;
    if (viewType == VIEW_ITEM) {
        View v = LayoutInflater.from(parent.getContext()).inflate(
                R.layout.list_row, parent, false);

        vh = new StudentViewHolder(v);
    } else {
        View v = LayoutInflater.from(parent.getContext()).inflate(
                R.layout.progressbar_item, parent, false);

        vh = new ProgressViewHolder(v);
    }
    return vh;
}

On my MainActivity that is where I put the LoadItems() to add the others items is :

mAdapter.setOnLoadMoreListener(new LoadMoreItems() {
        @Override
        public void LoadItems() {
            DataItemsList.add(null);
            mAdapter.notifyItemInserted(DataItemsList.size() - 1);

            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    //   remove progress item
                    DataItemsList.remove(DataItemsList.size() - 1);
                    mAdapter.notifyItemRemoved(DataItemsList.size());
                    //add items one by one
                    //When you've added the items call the setLoaded()
                    mAdapter.setLoaded();
                    //if you put all of the items at once call
                    // mAdapter.notifyDataSetChanged();
                }
            }, 2000); //time 2 seconds

        }
    });

For more information I just followed this Github repository(Note: this is using AsyncTask maybe it's useful as my answer, since I did it manually not with data from API but it should work as well) also this post was helpful to me endless-recyclerview-with-progress-bar

Also I don't know if you named it but I also found this post infinite_scrolling_recyclerview, maybe it could also help to you.

If it's not what you are looking for, let me know and tell me what's wrong with this code and I'll try to modify it as your like.

Hope it helps.

EDIT

Since you don't want to remove an item... I found I guess one guy that removes the footer only on this post : diseño-android-endless-recyclerview.

This is for ListView but I know you can adapt it to RecyclerView he's not deleting any item he's just putting Visible/Invisible the ProgressBar take a look : detecting-end-of-listview

Also take a look to : Commonsware EndlessAdapter and this question android-implementing-progressbar-and-loading-for-endless-list-like-android

Comments