Here is my solution. In FlickrFetchr.fetchItems I changed the signature to take a page number as a parameter like this:
public List<GalleryItem> fetchItems(int page) {
List<GalleryItem> items = new ArrayList<>();
try {
String url = Uri.parse("https://api.flickr.com/services/rest/")
.buildUpon()
.appendQueryParameter("method", "flickr.photos.getRecent")
.appendQueryParameter("api_key", API_KEY)
.appendQueryParameter("format", "json")
.appendQueryParameter("nojsoncallback", "1")
.appendQueryParameter("extras", "url_s")
.appendQueryParameter("page", String.valueOf(page))
.build().toString();
String jsonString = getUrlString(url);
Log.i(TAG, "Recieved JSON: " + jsonString);
JSONObject jsonBody = new JSONObject(jsonString);
parseItems(items, jsonBody);
} catch (IOException e) {
Log.e(TAG, "Failed to fetch items", e);
} catch (JSONException e) {
Log.e(TAG, "Failed to parse JSON", e);
}
return items;
}
Then I created a member variable ‘mPage’ at the top of the fragment to keep track of it. I also have a member variable to hold the GridLayoutManager. This allowed me to create an OnScrollListener at the bottom of the Fragment class.
RecyclerView.OnScrollListener mOnScrollListener = new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
// check if we are scrolling down
if (dy > 0) {
if (mGridLayoutManager.findLastVisibleItemPosition() > 80 * mPage){
new FetchItemsTask().execute(mPage++);
}
}
}
};
Once the GridLayoutManager gets to position 80 ( a little before the end of the list) I fetch another page by calling new FetchItemsTask().execute(mPage++) incrementing the page variable and also multiplying the position and the page number (ex. 80 * mPage) to make sure the requirement for fetching more data increases with the page number. A better algorithm for accomplishing this is out there but I didn’t want to spend too much time on this. The one problem that would arise is this; As more and more pages are added to the list, the difference between the LastVisibleItemPosition() and the actual end of the list will grow, triggering a FetchItems task a bit earlier each time.
To make this all work I had to also change the signature of the AsyncTask to accept an Integer object as input. I then pull it out in doInBackground and the list is appended in onPostExecute:
private class FetchItemsTask extends AsyncTask<Integer, Void, List<GalleryItem>> {
@Override
protected List<GalleryItem> doInBackground(Integer... pageNum) {
return new FlickrFetchr().fetchItems(pageNum[0]);
}
@Override
protected void onPostExecute(List<GalleryItem> galleryItems) {
mItems.addAll(galleryItems);
setupAdapter();
}
}