RecyclerView重新创建ViewHolder而不是重新绑定 [英] RecyclerView recreating ViewHolder instead of rebinding

查看:276
本文介绍了RecyclerView重新创建ViewHolder而不是重新绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基本上,我有一个带有聊天消息的 RecyclerView .情况如下:

  1. 我添加一条消息->使 RecyclerView 添加新的 ViewHolder
  2. 延迟约2秒
  3. 我更改了第一条消息并添加了一条新消息->应该使 RecyclerView 重新绑定第一条消息,并为第二条消息创建一个新的 ViewHolder .

我的问题出在第3步.删除第一个 ViewHolder ,然后创建一个新的,然后绑定它.这样会产生非常轻微的闪烁,这有点令人讨厌,并且所有这些都不应该发生.

我正在使用 DiffUtil 分发更改,整个设置涉及更多点,因此很难描述整个图片,但我将其缩小到以下范围:

DiffUtil 产生正确的结果,并为第一项调用 onItemRangeChanged ,为第二项调用 onItemRangeInserted .无论出于何种原因,然后都将第一个ViewHolder删除,并创建,添加和绑定新的on.

有人经历过类似的行为还是有线索为什么会这样呢?我尝试通过 RecyclerView 代码进行调试,但这是一场噩梦,我仍然不了解整个过程.

第一个 ViewHolder 无法反弹并且必须创建一个新的原因可能是什么原因?

如果我能提供更多信息,请要求它,我会尽力而为.

可以在此处找到显示问题的小型存储库:

解决方案

嘿,所以我自己弄清楚了,但是我仍然不完全理解为什么这样做是必要的.因此, RecyclerView 中的 ItemAnimator 决定更改后的ViewHolder是反弹还是重新创建.它将根据以下文章中提到的三个因素来做出决定.基本上,因为我使用的是 DiffUtil ,所以我只需要为 onItemRangeChanged 调用提供任意内容,它将重用 ViewHolder 而不是创建新的.

正是这篇文章帮助我理解了这个问题: https://medium.com/android-news/anatomy-of-recyclerview-part-1-a-search-for-a-viewholder-continued-d81c631a2b91

Basically I have a RecyclerView with chat messages. The scenario is as follows:

  1. I add a single message -> Causes RecyclerView to add a new ViewHolder
  2. Delay of about 2 seconds
  3. I change the first message and add a new one -> Should cause RecyclerView to rebind the first message and create a new ViewHolder for the second one.

My problem lies in step 3. as the first ViewHolder is removed and a new one is created and then bound. This produces a very slight flickering which is a little bit annoying and all in all this shouldn't happen.

I am using DiffUtil to dispatch changes, the whole setup is a little bit more involved so it is hard to describe the whole picture but I narrowed it down to this:

The DiffUtil produces the correct result and calls onItemRangeChanged for the first item and onItemRangeInserted for the second item. For whatever reason the first ViewHolder is then removed and a new on is created, added and then bound.

Did somebody experienced similar behaviour or has a clue why this could be the case? I tried to debug through the RecyclerView code but it is a nightmare and I still don't understand the whole thing. What could be the reason that the first ViewHolder cannot be rebound and a new one has to be created?

If I can provide any more information just ask for it and I will try my best.

A small repository showing the problem can be found here: https://github.com/MaxGierlachowski/recyclerview_viewholder_bug

If you look into the error logs and look at the 4th "MESSAGE" log you see that a onChanged and a onInserted are dispatched to the adapter but there is a new ViewHolder created for the onChanged one. I know that RecyclerView checks for a lot of things like animation completion and so on but I really would like to know why the ViewHolder isn't rebound but recreated.

EDIT: Something I figured out was that if that createViewHolder is called by the RecyclerView the ViewHolder that should be reused is inside the mChangedScrap list and mState.isPreLayout() is false so the function tryGetViewHolderForPositionByDeadline() doesn't search the mChangedScrap list and creates a new one. Still this shouldn't happen, the ViewHolder isn't even animated or something and it seems like all animations are finished at that point.

Small video of the flickering:

解决方案

Hey so I figured it out myself but I still don't fully understand why this is necessary. So the ItemAnimator inside RecyclerView decides whether a changed ViewHolder will be just rebound or recreated. It will decide it on three factors that are mentioned in the article below. So basically because I was using the DiffUtil I just had to provide some arbitrary to the onItemRangeChanged call and it would reuse the ViewHolder instead of creating a new one.

It was this article that help me understand the problem: https://medium.com/android-news/anatomy-of-recyclerview-part-1-a-search-for-a-viewholder-continued-d81c631a2b91

这篇关于RecyclerView重新创建ViewHolder而不是重新绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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