Android: как я могу загрузить больше данных в фоновом режиме в recyclerView

Я создаю новое приложение для Android, я почти закончил первый экран. Однако, как только я достигаю нижней части экрана, вместо загрузки новых данных приложение бросает меня прямо в начало страницы.

API, который я использую, отправит следующую страницу, когда я отправлю запрос на вторую страницу. Не могли бы вы рассказать мне, как я могу сделать приложение таким, чтобы оно автоматически отправляло запрос на вторую страницу, прежде чем пользователь дойдет до конца первой страницы.

Я использую библиотеку volley вместе с recyclerView и cardView. Не могли бы вы четко объяснить, где я должен вносить изменения, я новичок в разработке приложений.

Вот запрос залпа:

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);
}

person Rem    schedule 04.03.2017    source источник
comment
Вам помогло мое решение?   -  person Jimit Patel    schedule 04.03.2017


Ответы (2)


См. это. Это объяснено классным способом здесь.

В основном вам нужно onScrollChangeListener для обнаружения изменений прокрутки в вашем recyclerview, но само по себе это не поможет. Поэтому вам нужен способ проверить, достигли ли вы в настоящее время нижней части вашего recyclerview. так вот как вы это делаете:

Проверьте эту строку в приведенной выше ссылке

// 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);
        }

См. переменную visibleThreshold, в которой вы изменяете и применяете свое собственное значение для выполнения второго вызова.

давайте проверим это со значениями:

если visibleThreshold равно 0, и у вас есть 10 элементов в вашем списке, и вы находитесь на 6 элементе, а первый элемент является 0-м элементом: эта строка

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

интерпретируется как -> if (true && (0+6+0)>=10), что интерпретируется как false!

таким образом, второй вызов не будет сделан сейчас. это будет сделано, когда ваш последний элемент станет 10-м элементом (поскольку ваш порог равен 0)

Но теперь, если вы добавите порог 4, следующий вызов будет выполнен, поскольку условие теперь выполнено: интерпретируется как -> if (true && (0+6+4)>=10), что интерпретируется как истинное!

Подводя итог, можно сказать, что visibleThreshold — это то место, где вы добавляете свою логику, а в остальном вы можете реализовать шаблонный код по ссылке!

person MadScientist    schedule 07.03.2017

Для разбиения на страницы я использую следующий код

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);
        }
    }

Этот код будет вызывать API для следующей страницы всякий раз, когда прокрутка достигает нижней части прокрутки.

Также после каждого API я снова вызываю метод checkForMoreLoad(), чтобы проверить, требуются ли дополнительные данные или нет. И да, не забудьте добавить adapter.notifyItemRangeChanged() после добавления новых элементов в адаптер

person Jimit Patel    schedule 04.03.2017
comment
Я не могу понять, для чего используются hasMoreRequest и startAPI в конце, Android Studio также показывает ошибку в этих строках. - person Rem; 04.03.2017
comment
@Priyansh Bhatt извините, я не видел этот комментарий до сегодняшнего дня. hasMoreRequest - это флаг, который говорит, что вы хотите начать загрузку следующей страницы или не начинать, создайте переменную в начале вашего класса как boolean hasMoreRequest;. startAPI — это ваша собственная функция, которая вызывает сервер для получения данных следующей страницы. - person Jimit Patel; 05.09.2017