如何使用RecyclerView实现无尽列表?

本文翻译自:How to implement endless list with RecyclerView?

I would like to change ListView to RecyclerView . 我想将ListView更改为RecyclerView I want to use the onScroll of the OnScrollListener in RecyclerView to determine if a user scrolled to the end of the list. 我想在RecyclerView使用OnScrollListeneronScroll来确定用户是否滚动到列表的末尾。

How do I know if a user scrolls to the end of the list so that I can fetch new data from a REST service? 我如何知道用户是否滚动到列表的末尾,以便可以从REST服务获取新数据?


#1楼

参考:https://stackoom.com/question/1nN51/如何使用RecyclerView实现无尽列表


#2楼

OK, I did it by using the onBindViewHolder method of RecyclerView.Adapter. 好的,我通过使用RecyclerView.Adapter的onBindViewHolder方法做到了。

Adapter: 适配器:

public interface OnViewHolderListener {
    void onRequestedLastItem();
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {

    ...

    if (position == getItemCount() - 1) onViewHolderListener.onRequestedLastItem();
}

Fragment (or Activity) : 片段 (或活动)

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    contentView = inflater.inflate(R.layout.comments_list, container, false);
    recyclerView = (RecyclerView) mContentView.findViewById(R.id.my_recycler_view);
    adapter = new Adapter();
    recyclerView.setAdapter(adapter);

    ...

    adapter.setOnViewHolderListener(new Adapter.OnViewHolderListener() {
        @Override
        public void onRequestedLastItem() {
            //TODO fetch new data from webservice
        }
    });
    return contentView;
}

#3楼

I would try to extend used LayoutManager (eg LinearLayoutManager ) and override scrollVerticallyBy() method. 我会尝试扩展使用的LayoutManager (例如LinearLayoutManager )并重写scrollVerticallyBy()方法。 Firstly, I would call super first and then check returned integer value. 首先,我先调用super ,然后检查返回的整数值。 If the value equals to 0 then a bottom or a top border is reached. 如果该值等于0则到达底部或顶部边界。 Then I would use findLastVisibleItemPosition() method to find out which border is reached and load more data if needed. 然后,我将使用findLastVisibleItemPosition()方法找出到达哪个边界,并在需要时加载更多数据。 Just an idea. 只是一个主意。

In addition, you can even return your value from that method allowing overscroll and showing "loading" indicator. 另外,您甚至可以从该方法返回值,从而允许过度滚动并显示“正在加载”指示器。


#4楼

Make these variables. 进行这些变量。

private int previousTotal = 0;
private boolean loading = true;
private int visibleThreshold = 5;
int firstVisibleItem, visibleItemCount, totalItemCount;

Set on Scroll for recycler view. 在滚动条上设置以查看回收者视图。

mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {

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

        visibleItemCount = mRecyclerView.getChildCount();
        totalItemCount = mLayoutManager.getItemCount();
        firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();

        if (loading) {
            if (totalItemCount > previousTotal) {
                loading = false;
                previousTotal = totalItemCount;
            }
        }
        if (!loading && (totalItemCount - visibleItemCount) 
            <= (firstVisibleItem + visibleThreshold)) {
            // End has been reached

            Log.i("Yaeye!", "end called");

            // Do something

            loading = true;
        }
    }
});

Note : Make sure you are using LinearLayoutManager as layout manager for RecyclerView . 注意:确保将LinearLayoutManager用作RecyclerView布局管理器。

LinearLayoutManager mLayoutManager;
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);

and for a grid 和一个网格

GridLayoutManager mLayoutManager;
mLayoutManager = new GridLayoutManager(getActivity(), spanCount);
mRecyclerView.setLayoutManager(mLayoutManager);

Have fun with your endless scrolls !! 与您无尽的滚动乐趣! ^.^ ^。^

Update : mRecyclerView. 更新: mRecyclerView。 setOnScrollListener() is deprecated just replace with mRecyclerView.addOnScrollListener() and the warning will be gone! setOnScrollListener()仅仅是弃用替换mRecyclerView.addOnScrollListener()并警告将会消失! You can read more from this SO question . 您可以从这个SO问题中了解更多信息。

Since Android now officially support Kotlin, here is an update for the same - 由于Android现在已正式支持Kotlin,因此以下是该更新:

Make OnScrollListener 使OnScrollListener

class OnScrollListener(val layoutManager: LinearLayoutManager, val adapter: RecyclerView.Adapter<RecyclerAdapter.ViewHolder>, val dataList: MutableList<Int>) : RecyclerView.OnScrollListener() {
    var previousTotal = 0
    var loading = true
    val visibleThreshold = 10
    var firstVisibleItem = 0
    var visibleItemCount = 0
    var totalItemCount = 0

    override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
        super.onScrolled(recyclerView, dx, dy)

        visibleItemCount = recyclerView.childCount
        totalItemCount = layoutManager.itemCount
        firstVisibleItem = layoutManager.findFirstVisibleItemPosition()

        if (loading) {
            if (totalItemCount > previousTotal) {
                loading = false
                previousTotal = totalItemCount
            }
        }

        if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
            val initialSize = dataList.size
            updateDataList(dataList)
            val updatedSize = dataList.size
            recyclerView.post { adapter.notifyItemRangeInserted(initialSize, updatedSize) }
            loading = true
        }
    }
}

and add it to your RecyclerView like this 并像这样将其添加到您的RecyclerView中

recyclerView.addOnScrollListener(OnScrollListener(layoutManager, adapter, dataList))

For a full code example, feel free to refer this Github repo . 有关完整的代码示例,请随时参考此Github存储库


#5楼

Thanks to @Kushal and this is how I implemented it 感谢@Kushal,这就是我实现它的方式

private boolean loading = true;
int pastVisiblesItems, visibleItemCount, totalItemCount;

mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() 
{
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) 
    {
        if(dy > 0) //check for scroll down
        {
            visibleItemCount = mLayoutManager.getChildCount();
            totalItemCount = mLayoutManager.getItemCount();
            pastVisiblesItems = mLayoutManager.findFirstVisibleItemPosition();

            if (loading) 
            {
                if ( (visibleItemCount + pastVisiblesItems) >= totalItemCount) 
                {
                    loading = false;
                    Log.v("...", "Last Item Wow !");
                    //Do pagination.. i.e. fetch new data
                }
            }
        }
    }
});

Don't forget to add 不要忘记添加

LinearLayoutManager mLayoutManager;
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);

#6楼

I achieved an infinite scrolling type implementation using this logic in the onBindViewHolder method of my RecyclerView.Adapter class. 我在RecyclerView.Adapter类的onBindViewHolder方法中使用此逻辑实现了无限滚动类型的实现。

    if (position == mItems.size() - 1 && mCurrentPage <= mTotalPageCount) {
        if (mCurrentPage == mTotalPageCount) {
            mLoadImagesListener.noMorePages();
        } else {
            int newPage = mCurrentPage + 1;
            mLoadImagesListener.loadPage(newPage);
        }
    }

With this code when the RecyclerView gets to the last item, it increments the current page and callbacks on an interface which is responsible for loading more data from the api and adding the new results to the adapter. 使用此代码,当RecyclerView到达最后一项时,它将增加当前页面和接口上的回调,该接口负责从api加载更多数据并将新结果添加到适配器。

I can post more complete example if this isn't clear? 如果不清楚,我可以发布更完整的示例吗?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值