recyclerview 无休止的滚动减速

recyclerview endless scrolling slowdown

我阅读了有关实施 endless scrolling 的指南并进行了尝试。这是我对 loadNextDataFromApi 的实现:

public void loadNextDataFromApi(int page, String term) {
    movieService.getMovies(page, term)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Observer<List<Movie>>() {
                @Override
                public void onCompleted() {

                }

                @Override
                public void onError(Throwable e) {

                }

                @Override
                public void onNext(List<Movie> currentPageMovies) {
                    int start = allMovies.size();
                    allMovies.addAll(currentPageMovies);
                    adapter.notifyItemRangeInserted(start, currentPageMovies.size());
                }
            });
}

allMovies 包含给定搜索的所有电影。这最初工作正常但滚动最终加载速度较慢,从平滑滚动到一次 3 部电影(为每个请求指定的数量)。我认为这是因为列表增长并占用越来越多的内存。文章提到,

In order for the pagination system to continue working reliably, you should make sure to clear the adapter of items (or notify adapter after clearing the array) before appending new items to the list

但是将上面的 onNext 实现更改为此会打破无限滚动:

            @Override
            public void onNext(List<Movie> currentPageMovies) {
                allMovies.clear();
                adapter.notifyDataSetChanged();
                int start = allMovies.size();
                allMovies.addAll(currentPageMovies);
                adapter.notifyItemRangeInserted(start, currentPageMovies.size());
            }

是否需要在 allMovies 列表中保留 List 的前几页以便向上滚动?同时无限滚动会导致OOM,具体取决于页数

我一直致力于通过 api 调用进行无休止的滚动,因此我可以与您分享我的代码,因为我发现我的列表运行良好。

先用这个方法获取recyclerview已经到达最后位置

public void setRecyclerViewLastPositionListner(RecyclerView rv, final LinearLayoutManager mLayoutManager, final OnLastPositionReached onLastPositionReached) {
    rv.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
                userScrolled = true;
            }
        }

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

            super.onScrolled(recyclerView, dx, dy);
            // Here get the child count, item count and visibleitems
            // from layout manager

            visibleItemCount = mLayoutManager.getChildCount();
            totalItemCount = mLayoutManager.getItemCount();
            pastVisiblesItems = mLayoutManager.findFirstVisibleItemPosition();

            // Now check if userScrolled is true and also check if
            // the item is end then update recycler view and set
            // userScrolled to false
            if (userScrolled && (visibleItemCount + pastVisiblesItems) == totalItemCount) {
                userScrolled = false;
                if (onLastPositionReached != null) onLastPositionReached.onReached();
            }
        }
    });
}

此处使用接口

public interface OnLastPositionReached {
    void onReached();
}

一样使用它
UtilitiesV2.getInstance().setRecyclerViewLastPositionListner(yourRecyclerView, mLayoutManager, new UtilitiesV2.OnLastPositionReached() {
            @Override
            public void onReached() {
                callEBookApi();
            }
        });

这些变量保存下一个 api 调用的开始位置。

  long start = 0;
    private int lastReceivedListSize = 0;
      int DEFAULT_LIMIT = 20;

考虑在这里给您的 api 打电话。

 private void callEBookApi() {
        start = booksAdapter.getItemCount();
        if (start != 0 & lastReceivedListSize < DEFAULT_LIMIT)
            return;
        BeanLimit beanLimit = new BeanLimit();
        beanLimit.setLimit(DEFAULT_LIMIT);
        beanLimit.setStartpoint(start);
        showProgressBar();
        try {
            callWebServicePost(Interactor.RequestCode_getEbooks, Interactor.Tag_getEbooks, Interactor.Method_getEbooks, new JSONObject(new Gson().toJson(beanLimit)), false, new OnResponseListener() {
                @Override
                public void onSuccess(int requestCode, Response responsePacket) {

                    hideProgressBar();

                        ArrayList<BookBean> list = responsePacket.getResponsePacket().getBooksList();
                        lastReceivedListSize = list.size();
                        updateListData(list);

                }

                @Override
                public void onError(int requestCode, ErrorType errorType) {
                    FragmentEbooks.super.onError(requestCode, errorType);
                    hideProgressBar();
                    UtilProject.getInstance().showNothingToDisplayLayout(FragmentEbooks.this);
                }
            });
        } catch (JSONException e) {
            e.printStackTrace();
            hideProgressBar();
        }
    }




    private void updateListData(ArrayList<BookBean> list) {
        if (list == null) listBooks = new ArrayList<>();
        booksAdapter.insertItemsInList(list);
        if (booksAdapter.getList().size() != 0) {
           // UtilProject.getInstance().hideNothingToDisplayAndProgressBar(this);   /*here you show placeholder if list empty*/
        } else {
           // UtilProject.getInstance().showNothingToDisplayLayout(this);
        }
    }





    public void insertItemsInList(ArrayList<InvitationBean> myList) {
        if (list == null) list = new ArrayList<>();
        int lastIndex = list.size();
        list.addAll(myList);
        notifyItemRangeInserted(lastIndex, myList.size());  /*use this line for smooth scrolling if you use notifyDataSetChanged it will load all data again*/
//        notifyDataSetChanged();
    }

希望对您有所帮助。