RecycerView paging basics

Scenario: There are 1000 pictures on the server. It’s not a good idea to download all of the 1000 pictures at one time. Usually, the API will fetch 100 images per time. And then fetch more images based on the request.

For instance, when the user scroll down to the end(or almost) of the RecyclerView, I want to load more items automatically.

The question is How can I know it is the end of the recycler view so I can send the request to the server.

At first, I had no idea. Then I searched a little, finding that we need to add a scroll listener: mRecyclerView.addOnScrollListener(). After got this hint, I tried to solve it myself. For this listener, there are two methods. The onScrolled()method is useful here.

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

Af first, I thought the end means I cannot scroll down anymore. In previous method, the dy: The amount of vertical scroll. This idea seems not good.

Why this is the end? Because I cannot scroll anymore. OK, but this is the phenomenon not the reason. If we ask one more question, why I cannot scroll anymore? Because we run out of the pictures downloaded from the server. Yeah!

Then, there is a solution. If we know the number of pictures the user have scrolled. Then compare it with the number in the adapter which stores all of the data. We can decide to load more.

First visible item: It is first picture on the screen. layoutManager.findFirstVisibleItemPosition()

Current visible items(Blue): The account of visible items on the current screen. We can get the number by calling layoutManager.getChildCount()

All items: This includes visible and non-visible items (the grey, blue, yellow part). Get this number by calling layoutManager.getItemCount(). When we create the adapter, we will pass the data (usually in list). The size should be the same.

if the (fistVisiblePosition + currentVisibleItems >= allItems), then we need to send request to server to get the new pictures. In this way, user have to wait for a while to see the next picture in the next page. Thus, usually, we will add one more number — threshold. Say the threshold is 10. We will start to load the next page when we see the 90th picture instead of see the 100th picture.


if(dy > 0){// now it is scrolling down
if
(firstVisiblePosition + currentVisibleNumber + loadingThreshold > totalItemNumber) {
currentPage ++;
loadMore(currentPage);
}
}

A problem for this code, is that if the user keeps scroll down again and again, that condition is true, therefore, the currentPage keeps increasing.

We should create a flag to tell the current app that “I sent your request to the server, now I’m waiting for the response. So stop send more request.” We add one more flag: isLoading.

boolean isLoading = false; 
if(dy > 0){// now it is scrolling down
if( !isLoading&& firstVisiblePosition
+ currentVisibleNumber + loadingThreshold > totalItemNumber) {
currentPage ++;
isLoading = true;
loadMore(currentPage);

}
}

After the load finished, then set the isLoading to false again.

Note:Pay attenttion to the asynchronous method. e.g. The loadMore is an AsyncTask, then we need to set the isLoading =false on the onPostExecute() method.

So far, this problem is solved.

Then after get the items of page 2 from the server. We can add them to current adapter list items. Use list.addAll() method instead of list = newlist. The notifyDataSetChanged() to notify the adapter. In this way, if the user scroll up, we don’t need to send request to get the items in page 1.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.