即使 RecyclerView.findViewHolderForAdapterPosition() 在该位置返回 null,也永远不会在视图上调用 onBindViewHolder() [英] onBindViewHolder() is never called on view at position even though RecyclerView.findViewHolderForAdapterPosition() returns null at that position

查看:28
本文介绍了即使 RecyclerView.findViewHolderForAdapterPosition() 在该位置返回 null,也永远不会在视图上调用 onBindViewHolder()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含 13 个项目的列表(尽管可以添加或删除项目),位置为 0-12.当第一次显示包含 RecyclerView 的片段时,用户只能看到位置 0 到 7(位置 7 只有一半可见).在我的适配器中,我 Log 每次绑定/绑定视图持有者(如果语法适用于此,则为 idk)并记录其位置.

I have a list with 13 items (although items may be added or removed), positions 0-12. When the fragment containing the RecyclerView is first shown, only positions 0 through 7 are visible to the user (position 7 being only half visible). In my adapter I Log every time a view holder is binded/bound (idk if grammar applies here) and record its position.

适配器

@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
    Log.d(TAG, "onBindViewHolder() position: " + position);
    ...
}

从我的 Log 我看到位置 0-7 是绑定的:

From my Log I see that positions 0-7 are bound:

我有一个 selectAll() 方法,它通过适配器位置获取每个 ViewHolder.如果返回的 holder 不是 null 我使用返回的 holder 来更新视图以显示它被选中.如果返回的持有人是 null 我调用 selectOnBind() 一个方法,该方法标记该位置的视图更新以显示它在绑定时被选中而不是实时被选中,因为它不是当前显示:

I have a selectAll() method that gets each ViewHolder by adapter position. If the returned holder is NOT null I use the returned holder to update the view to show it's selected. If the returned holder IS null I call selectOnBind() a method that flags the view at that position update to show it's selected when it's binded rather than in real time since it's not currently shown:

public void selectAll() {
    for (int i = 0; i < numberOfItemsInList; i++) {
        MyAdapter.ViewHolder holder = (MyAdapter.ViewHolder)
                mRecyclerView.findViewHolderForAdapterPosition(i);

        Log.d(TAG, "holder at position " + i + " is " + holder);

        if (holder != null) {
            select(holder);
        } else {
            selectOnBind(i);
        }
    }
}

在这个方法中,我Log holder 连同它的位置:

In this method I Log the holder along with its position:

所以到目前为止一切似乎都很正常.我们有位置 0-7 显示,根据 Log 这些是绑定的位置.当我点击 selectAll() 而不更改可见视图(滚动)时,我看到位置 0-7 已定义,8-12 为 null.到目前为止一切顺利.

So up to this point everything seems normal. We have positions 0-7 showing, and according to the Log these are the positions bound. When I hit selectAll() without changing the visible views (scrolling) I see that positions 0-7 are defined and 8-12 are null. So far so good.

这就是有趣的地方.如果在调用 selectAll() 之后我进一步向下滚动列表位置 8 和 9 没有显示它们被选中.

Here's where it gets interesting. If after calling selectAll() I scroll further down the list positions 8 and 9 do not show they are selected.

在检查 Log 时,我看到这是因为它们从未被绑定,即使它们被报告为 null:

When checking the Log I see that it's because they are never bound even though they were reported to be null:

更令人困惑的是,这种情况并非每次都发生.如果我首先启动应用程序并测试它可能会工作.但事后似乎没有失败.我猜这与被回收的视图有关,但即便如此,它们也不必绑定吗?

Even more confusing is that this does not happen every time. If I first launch the app and test this it may work. But it seems to happen without fail afterwards. I'm guessing it has something to do with the views being recycled, but even so wouldn't they have to be bound?

编辑 (6-29-16)
在 AndroidStudio 更新后,我似乎无法重现该错误.它按我的预期工作,绑定了空视图.如果这个问题再次出现,我会回到这个帖子.

EDIT (6-29-16)
After an AndroidStudio update I cannot seem to reproduce the bug. It works as I expected it to, binding the null views. If this problem should resurface, I will return to this post.

推荐答案

发生这种情况是因为:

  • 视图不会添加到回收器视图中(getChildAt 将不起作用,该位置将返回 null)
  • 它们也被缓存(onBind 不会被调用)
  • The views are not added to the recyclerview (getChildAt will not work and will return null for that position)
  • They are cached also (onBind will not be called)

调用 recyclerView.setItemViewCacheSize(0) 将解决这个问题".

Calling recyclerView.setItemViewCacheSize(0) will fix this "problem".

因为默认值是 2(RecyclerView.Recycler 中的 private static final int DEFAULT_CACHE_SIZE = 2;),你总是会得到 2 个不会调用 onBind 但没有添加到回收器

Because the default value is 2 (private static final int DEFAULT_CACHE_SIZE = 2; in RecyclerView.Recycler), you'll always get 2 views that will not call onBind but that aren't added to the recycler

这篇关于即使 RecyclerView.findViewHolderForAdapterPosition() 在该位置返回 null,也永远不会在视图上调用 onBindViewHolder()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆