Android: How can I load more data in the background in recyclerView
Asked Answered
G

2

0

I am creating a new android app, I have nearly completed the first screen. However, as soon as I reach the bottom of the screen, instead of loading new data, the app throws me right to the beginning of the page.

The API that I'm using will send the next page when I send a request for the second page. Can you please tell me how can I make the app such that, it automatically sends the request for the second page, before the user reaches the end of the first page.

I'm using volley library along with recyclerView and cardView. Can you please explain clearly as to where am I supposed to make changes, I am new to app development.

Here is the volley request:

private void discoverMovies() {

    final ProgressDialog progressDialog = new ProgressDialog(getContext());
    progressDialog.setMessage("Fetching Data From DB");
    progressDialog.show();

    //Requesting the data.....
    StringRequest stringRequest = new StringRequest(Request.Method.GET, tempURL,
            new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    try {
                        progressDialog.dismiss();
                        JSONObject parentObject = new JSONObject(response);
                        JSONArray parentArray = parentObject.getJSONArray("results");

                        for (int i = 0; i < parentArray.length(); i++) {
                            JSONObject object = parentArray.getJSONObject(i);
                            movieModel model = new movieModel(
                                    object.getString("title"),
                                    object.getString("overview"),
                                    object.getString("release_date"),
                                    object.getString("poster_path"),
                                    object.getInt("id"),
                                    object.getBoolean("adult"),
                                    object.getInt("vote_count"),
                                    object.getDouble("vote_average"),
                                    object.getString("original_language"),
                                    object.getString("backdrop_path")
                            );

                            movieModels.add(model);
                            adapter = new cardViewAdapter(getContext(), movieModels);
                            recyclerView.setAdapter(adapter);
                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }

                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    progressDialog.dismiss();
                    Toast.makeText(getActivity(), error.getLocalizedMessage(), Toast.LENGTH_LONG).show();
                }
            });

    RequestQueue requestQueue = Volley.newRequestQueue(getContext());
    requestQueue.add(stringRequest);
}
Gennie answered 4/3, 2017 at 6:32 Comment(1)
Did my solution helped you?Acanthoid
C
2

Refer this. Its explained in a cool fashion here.

Basically you need an onScrollChangeListener to detect scroll changes in your recyclerview but that alone wont help. So you need a way to check whether you are currently reaching the bottom of your recyclerview. so here's how you do it:

Check this line in the above link

// If it isn't currently loading, we check to see if we have breached
        // the visibleThreshold and need to reload more data.
        // If we do need to reload some more data, we execute onLoadMore to fetch the data.
        if (!loading && (firstVisibleItem + visibleItemCount + visibleThreshold) >= totalItemCount ) {
            loading = onLoadMore(currentPage + 1, totalItemCount);
        }

See the variable visibleThreshold that is where you modify and apply you own custom value to make the second call.

lets check that with values:

if visibleThreshold is 0 and you have 10 items in your list and you`re on the 6 item and the first item is the 0th item: the this line

if (!loading && (firstVisibleItem + visibleItemCount + visibleThreshold) >= totalItemCount )

interprets as -> if (true && (0+6+0)>=10) which interprets as false!

thus the second call wont be made now. it will be made when you lastitem is the 10th item (as your threshold is 0)

But now if you add a threshold of 4, the next call is made as the condition now is satisfied: interprets as -> if (true && (0+6+4)>=10) which interprets as true!

Summarizing, the visibleThreshold is where you add your logic, rest you can implement the boiler plate code from the link!

Contorted answered 7/3, 2017 at 16:18 Comment(0)
A
1

For pagination I use following code

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                if (hasMoreRequest) {
                    if (dy > 0) { //check for scroll down
                        checkForMoreLoad();
                    }
                }
            }
        });

private void checkForMoreLoad() {
        final Handler handler = new Handler();
        Runnable checkForMoreData = new Runnable() {
            @Override
            public void run() {
                if (null != recyclerView) {
                    int visibleItemCount = recyclerView.getLayoutManager().getChildCount();
                    int totalItemCount = recyclerView.getLayoutManager().getItemCount();
                    int pastVisibleItems = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition();
                    onScrollToLoad(visibleItemCount, pastVisibleItems, totalItemCount);
                }
            }
        };
        handler.postDelayed(checkForMoreData, 100);
    }

    private void onScrollToLoad(int visibleItemCount, int pastVisibleItems, int totalItemCount) {
        if ((visibleItemCount + pastVisibleItems) >= totalItemCount && hasMoreRequest) {
            if (BuildConfig.DEBUG)
                Log.d(TAG, "onScroll lastInScreen - so load more");
            startApi(page + 1);
        }
    }

This code will call API for next page, whenever scroll reaches to bottom of the scroll.

Also after each API, I call checkForMoreLoad() method again to check whether more data is required or not. And yes don't forget to add adapter.notifyItemRangeChanged() after adding new elements to adapter

Acanthoid answered 4/3, 2017 at 6:50 Comment(2)
I can't understand what is the use of hasMoreRequest and the startAPI at the end, Android Studio is also showing error on these lines.Gennie
@Priyansh Bhatt sorry I didn't saw this comment till today. hasMoreRequest is a flag that says so do want to start next page download or not to start, make a variable in starting off your class as boolean hasMoreRequest;. startAPI is your own function which calls server to fetch data of next page.Acanthoid

© 2022 - 2024 — McMap. All rights reserved.