【问题标题】:RecyclerView Infinite Scroll listener being called twiceRecyclerView Infinite Scroll 监听器被调用两次
【发布时间】:2016-02-09 06:46:59
【问题描述】:

我有一个RecyclerView,我试图在其中实现无限滚动功能。问题是,OnScrolled 方法中的 if 语句中的代码被执行了两次。这是我当前的代码:

public abstract class InfiniteScroll extends RecyclerView.OnScrollListener {

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

private int current_page = 1;

public InfiniteScroll(LinearLayoutManager layoutManager) {
    mLayoutManager = layoutManager;
}

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

    visibleItemCount = recyclerView.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

        // Do something
        current_page++;
        Log.d("moreitems", "why is this being called twice?");
        loadMore(current_page);

        loading = true;
    }
}

public abstract void loadMore(int current_page);
}

此代码是作为单独 SO 问题的答案发布的,其他示例的功能似乎相似,但是当到达 RecyclerView 的底部时,我仍然得到 loadMore() 方法执行两次,我不知道为什么.

【问题讨论】:

  • 使用LimearLayoutManager#findLast[Completely]VisibleItemPosition()方法

标签: android android-recyclerview


【解决方案1】:

之所以会调用它,是因为当您加载更多项目时,会再次调用 onScrolled。

如果在布局计算后可见项目范围发生变化,也会调用此回调。在这种情况下,dx 和 dy 将为 0。

所以你可以检查 if (!loading &amp;&amp; dy&gt;0) 还有

【讨论】:

  • 顺便说一句,我已将其添加到 onScrolled 的开头,所以不会执行任何操作,您是否有理由将它与 !loading 一起使用?我看到它可以与 @987654324 一起使用@ 也一样,但是为什么要执行中间代码,可以吗?我把它向上移动了:if(dy &lt;= 0) return;,我的意思是我的代码没有发现任何问题,但也许你遇到了一些罕见的情况?
【解决方案2】:

试试这个:

 public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
                totalItemCount = linearLayoutManager.getItemCount();
                lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
                if (!loading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
                    loading = true;
                    // End has been reached
                    // Do something
                       current_page++;
                       Log.d("moreitems", "why is this being called twice?");
                       loadMore(current_page);

                }
            }

【讨论】:

  • 你在哪里设置加载回false这个解决方案?否则加载保持true 并再次到达列表末尾不会触发另一个加载。
  • 我在这里发布了一个示例代码:stackoverflow.com/questions/35253695/…
  • 添加加载 = false;在 loarmore() 方法中(最后一行)。完成所有内容后,您应该将 loading 设置为 false。
【解决方案3】:

我刚遇到类似的情况,但解决方案与上面的答案有很大不同。

就我而言,我有一个自定义 RecyclerViewFragment,它将在数据加载开始时设置 RecyclerView。我在该设置方法块中添加了一个自定义 OnScrollListener。

我的 OnScrollListener 被调用两次的原因是,我不小心在我的 RecyclerView 中添加了两个 OnScrollListener。因此,这两个监听器都会监听“滚动到最后”动作并为它做一些事情。

所以我只是在调用设置方法之前删除了我的 RecyclerView 的所有 OnScrollListener,以确保只有一个 OnScrollListener。

希望对您有所帮助。

【讨论】:

    【解决方案4】:
    if (layoutManager.findLastCompletelyVisibleItemPosition() == 
    recyclerAdapter.getItemCount() - 1) {
         //load more items code is here
    }
    

    这会起作用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 2019-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多