android - RecyclerView 和 Adapter 数据更新

标签 android android-recyclerview

这是一个关于 RecyclerView 内部行为的问题,适用于了解其机制或愿意深入研究源代码的人。我想要一个通过引用源来支持的答案。

原始问题

(向下滚动到“换句话说”以获得更集中的问题)

我需要了解 notify* 操作(例如,notifyItemInserted())是如何排入队列的。假设我有一个由这个列表备份的适配器:

ArrayList<String> list = Arrays.asList("one", "three", "four");

我想添加缺少的值 zerotwo

示例 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() 方法结束。我可以将他们的操作排入队列,但是:

  1. 如果已经有内部队列,我不想这样做,而且肯定有
  2. 我不知道如果两个 Action 之间没有布局传递会发生什么,请参见示例 3。

换句话说

要更新回收站,必须执行 4 个操作:

  1. 我实际上改变了数据模型(例如,在后备数组中插入一些东西)
  2. 我调用 adapter.notify*()
  3. 回收者接到电话
  4. Recycler 执行操作(例如调用适配器上的 getItem*()onBind())并列出更改。

在没有并发的情况下很容易理解,它们是按顺序发生的:

1. => 2. => 3. => 4. => (new update) 1. => 2. => 3. => 4. ...

让我们看看步骤之间会发生什么。

  • 1.2. 之间:我会说在更改数据后立即调用 notify() 是开发人员的责任。没关系。
  • 2.3. 之间:这会立即发生,这里没有问题。
  • 3.4. 之间:这不会立即发生! AFAIK。所以很有可能在步骤 34 之间有一个新的更新(步骤 12)之前的更新

我想了解在这种情况下会发生什么。 我们应该如何表现? 我是否应该确保在插入新内容之前确实执行了上一次更新的第 4 步?如果有怎么办?

最佳答案

之前我也想过类似的问题,我决定:

  1. 如果我想直接在列表末尾插入超过 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.
    
  2. 如果我想直接在列表末尾插入超过 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());
    
  3. 如果我想在列表的不同位置插入超过 1 个项目, 类似于 2。

希望这能有所帮助。

关于android - RecyclerView 和 Adapter 数据更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40507844/

相关文章:

android - 显示当前聚焦的 View (即使没有布局选择器)

android - 文件描述符 3 的 bash 重定向是读取 tcp 端口和写入文本文件的最有效方法吗?

java - 使用 url 加载 imaeview 的任何更快的方法

android - "This Feature is not available on this device"请求 DND 权限时出现此错误

android - 在多个布局文件-android 上应用 recyclerView 适配器

Android:如何在没有强制关闭的情况下处理try catch中的错误

java - 修改自定义 RecyclerView 的项目

java - 如何使 RecyclerView 不可点击并将 onClick 事件传递给父 View ?

java - RecyclerView点击事件不起作用

java - 在另一个 Activity 中使用 RecyclerView 适配器的 ArrayList