这是一个关于RecyclerView内部行为的问题,针对了解其机制或愿意深入源代码的人。我希望得到一份有源代码支持的答案。
原始问题
(向下滚动到“换言之”以获取更专注的问题)
我需要了解如何排队 notify*
操作(例如,notifyItemInserted()
)。想象一下,我有一个由此列表支持的适配器:
ArrayList<String> list = Arrays.asList("one", "three", "four");
我想要添加缺失的值zero
和two
。
示例1
list.add(1, "two");
// notify the view
adapter.notifyItemInserted(1);
// Seconds later, I go on with zero
list.add(0, "zero");
// notify the view
adapter.notifyItemInserted(0);
这很简单明了,没有什么需要解释的。
示例2
但如果这两个动作非常接近,并且它们之间没有布局传递怎么办?
list.add(1, "two");
list.add(0, "zero”);
我现在该做什么?
adapter.notifyItemInserted(1);
adapter.notifyItemInserted(0);
或者也许
adapter.notifyItemInserted(2);
adapter.notifyItemInserted(0);
从适配器的角度来看,列表立即从one, three, four
切换到zero, one, two, three, four
,因此第二个选项似乎更合理。
示例3
list.add(0, “zero”);
adapter.notifyItemInserted(0);
list.add(2, “two”);
adapter.notifyItemInserted(...)
现在怎么样?1
还是2
?列表在立即更新后,但我确定它们之间没有布局传递。
问题
你已经了解了主要问题,我想知道在这些情况下应该如何行事。实际情况是我有多个异步任务最终会在一个insert()
方法中结束。我可以排队他们的操作,但:
- 如果已经有一个内部队列,我不想那样做,而且肯定有
- 如果两个动作之间没有布局传递,例如示例3,我不知道会发生什么。
换句话说
为了更新回收站,必须执行4个操作:
- 我实际上改变了数据模型(例如,将某些内容插入备份数组中)
- 我调用
adapter.notify*()
- 回收站接收到调用
- 回收站执行操作(例如,在适配器上调用
getItem*()
和onBind()
),并布置更改。
当没有并发时很容易理解它们按顺序发生:
1. => 2. => 3. => 4. => (new update) 1. => 2. => 3. => 4. ...
让我们看看步骤之间会发生什么。
- 步骤1和步骤2之间:我认为开发者有责任在修改数据后立即调用notify()。这没问题。
- 步骤2和步骤3之间:这会立即发生,没有问题。
- 步骤3和步骤4之间:这并不是立即发生的!据我所知。因此,在上一次更新的步骤3和步骤4之间可能会出现新的更新(步骤1和2)。
我想了解在这种情况下会发生什么。 我们应该怎么做? 我应该确保上一次更新的步骤4已经完成,然后再插入新的内容吗?如果是,如何操作?
notifyItemInserted(position)
总是被视为notifyItemRangeInserted(position, 1)
。在这里使用哪一个并没有区别。 - natario