20

I have one RecyclerView and I added list of data into the RecyclerView. I wanted to add more data in list, when last RecyclerView item is visible on screen. After that I want to make a web service call and update the RecyclerView data. How can I achieve this?

Any suggestions?

4

5 回答 5

19

一种选择是编辑您的LayoutManager. 这里的想法是找到最后一个可见项目的位置。如果该位置等于数据集的最后一项,则应触发重新加载。

    @Override
    public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {

        final int result = super.scrollVerticallyBy(dy, recycler, state);

        if (findLastVisibleItemPosition() == mData.length - 1) {
           loadMoreData();
        } 

        return result;

    }

    @Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
        super.onLayoutChildren(recycler, state);

        if (findLastVisibleItemPosition() == mData.length - 1) {
           loadMoreData();
        } 
    }

或者,您可以通过适配器的onBindViewHolder方法执行此操作,尽管这无疑有点“黑客”:

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (position == mData.length - 1) {
            // load more data here.
        }

        /// binding logic
    }

第三个选项是将 OnScrollListener 添加到 RecyclerView。@velval 在此页面上的回答很好地解释了这一点。

无论您选择哪个选项,您还应该包含代码以防止数据加载逻辑触发太多次(例如,在先前获取更多数据的请求完成并返回新数据之前)。

于 2016-01-26T09:42:02.173 回答
11

如果有人偶然发现这篇文章,这是一个关于如何做的快速简单的教程:

您需要做的就是:

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
    }

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        int visibleItemCount        = lm.getChildCount();
        int totalItemCount          = lm.getItemCount();
        int firstVisibleItemPosition= lm.findFirstVisibleItemPosition();

        // Load more if we have reach the end to the recyclerView
        if ( (visibleItemCount + firstVisibleItemPosition) >= totalItemCount && firstVisibleItemPosition >= 0) {
            loadMoreItems();
        }
    }
});

然后你的loadMoreItems()应该是这样的:

private void loadMoreItems() {
    // init offset=0 the frist time and increase the offset + the PAGE_SIZE when loading more items
    queryOffset = queryOffset + PAGE_SIZE;
    // HERE YOU LOAD the next batch of items
    List<Items> newItems = loadItems(queryOffset, PAGE_SIZE);

    if (newItems.size() > 0) {
        items.addAll(newItems);
        adapter.notifyDataSetChanged();
    }
}
于 2017-05-23T14:28:27.110 回答
0
@Override
public void onBindViewHolder(final RecyclerView.ViewHolderholder, int position) {

    if (!list.isEmpty() || list== null) {

        if (position == (list.size() - 1)) {

            // add new data (add data to list)
            this.notifyDataSetChanged();

        }

    }


}
于 2017-07-08T19:51:37.430 回答
0

另请参阅Android - 检测 RecyclerView 中的最后一个项目何时可见

private fun isLastItemVisible(): Boolean {
    val layoutManager = recycler_view.layoutManager
    val position = layoutManager.findLastCompletelyVisibleItemPosition()
    return position >= adapter.itemCount - 1
}
于 2020-08-07T13:42:48.067 回答
0

看到了上述许多答案,但我的答案不同,它也适用于您的情况。我的方法是基于 recylerview 的滚动状态。保持在变量“check”之下,这应该只在 api 响应时更新一次。将以下代码放入您的 api 响应中。如果您只想在每次调用 api 时处理最后一项。

final boolean[] check = {true};
    recyclerView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
        @Override
        public void onScrollChanged() {
            if (!recyclerView.canScrollVertically(1)) {
                // last item of recylerview reached.
                if (check[0]) {
                    //your code for last reached item
                    scroll_handler.setVisibility(View.GONE);
                }
            } else {
                scroll_handler.setVisibility(View.VISIBLE);
                check[0] = false;
            }
        }
    });

如果您想每次都处理最后一件物品,请按以下步骤操作

recyclerView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
    @Override
    public void onScrollChanged() {
        if (!recyclerView.canScrollVertically(1)) 
            // Bottom of recyler view.
            arrow_img.setRotation(180);
        }
    }
});
于 2019-12-19T07:06:50.177 回答