这是一个关于 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
但是如果两个 Action 彼此非常接近,并且中间没有布局传递怎么办?
list.add(1, "two");
list.add(0, "zero”);
我现在该怎么办?
adapter.notifyItemInserted(1);
adapter.notifyItemInserted(0);
或许
adapter.notifyItemInserted(2);
adapter.notifyItemInserted(0);
?从适配器的角度来看,列表立即从 one,3,4
切换到 0,1,2,3,4
,所以第二个选项似乎更合理。
示例 3
list.add(0, “zero”);
adapter.notifyItemInserted(0);
list.add(2, “two”);
adapter.notifyItemInserted(...)
现在呢? 1
还是 2
?列表在之后立即更新,但我确信两者之间没有布局传递。
问题
您遇到了主要问题,我想知道在这些情况下我应该如何表现。真实情况是我有多个异步任务以 insert()
方法结束。我可以将他们的操作排入队列,但是:
- 如果已经有内部队列,我不想这样做,而且肯定有
- 我不知道如果两个 Action 之间没有布局传递会发生什么,请参见示例 3。
换句话说
要更新回收站,必须执行 4 个操作:
- 我实际上改变了数据模型(例如,在后备数组中插入一些东西)
- 我调用
adapter.notify*()
- 回收者接到电话
- Recycler 执行操作(例如调用适配器上的
getItem*()
和onBind()
)并列出更改。
在没有并发的情况下很容易理解,它们是按顺序发生的:
1. => 2. => 3. => 4. => (new update) 1. => 2. => 3. => 4. ...
让我们看看步骤之间会发生什么。
- 在 1. 和 2. 之间:我会说在更改数据后立即调用 notify() 是开发人员的责任。没关系。
- 在 2. 和 3. 之间:这会立即发生,这里没有问题。
- 在 3. 和 4. 之间:这不会立即发生! AFAIK。所以很有可能在步骤 3 和 4 之间有一个新的更新(步骤 1 和 2)之前的更新。
我想了解在这种情况下会发生什么。 我们应该如何表现? 我是否应该确保在插入新内容之前确实执行了上一次更新的第 4 步?如果有怎么办?
最佳答案
之前我也想过类似的问题,我决定:
如果我想直接在列表末尾插入超过 1 个项目并且 想要为所有人制作动画,我应该:
list.add("0"); list.add("1"); adapter.notifyItemRangeInserted(5, 2); // Suppose there were 5 items before so "0" has index of 5 and we want to insert 2 items.
如果我想直接在列表末尾插入超过 1 个项目,但是 想要为每个插入的项目获取单独的动画,我应该:
list.add("0"); list.add("1"); adapter.notifyItemInserted(0); mRecyclerView.postDelayed(new Runnable() { @Override public void run() { // before this happens, Be careful to call other notify* methods. Never call notifyDataSetChanged. adapter.notifyItemInserted(1); } }, mRecyclerView.getItemAnimator().getAddDuration());
- 如果我想在列表的不同位置插入超过 1 个项目, 类似于 2。
希望这能有所帮助。
关于android - RecyclerView 和 Adapter 数据更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40507844/