Android 数据绑定 ObservableList 行为问题

Android data binding ObservableList behaviour issue

我发现很难发现 android.databinding.ObservableList 作为数据绑定功能的真正存在理由。

起初它看起来像是一个很酷的显示列表的工具,通过 data binding,通过 xml 添加它们到 RecyclerView。 为此,我做了一个 BindingAdapter 这样的:

@BindingAdapter(value = {"items"}, requireAll = false)
public static void setMyAdapterItems(RecyclerView view, ObservableList <T> items) {
    if(items != null && (view.getAdapter() instanceof MyAdapter)) {
        ((GenericAdapter<T>) view.getAdapter()).setItems(items);
    }
}

这样,我可以在设置了 MyAdapterRecyclerView 中使用属性 app:items 来更新它的项目。

现在 ObservableList 的最佳功能是您可以向它添加一个 OnListChangedCallback,它处理其中 RecyclerView 到 add/move/remove/change 项中可用的相同事件无需实际重新加载整个列表。

所以我想实现的逻辑是:

  1. 我从一个空的开始 MyAdapter
  2. 当我的项目从我的 API 中获取时,我实例化一个 ObservableArrayList 包装它们并将其传递给 binding
  3. 数据绑定调用我的 BindingAdapter 将项目传递给 MyAdapter
  4. MyAdapter 收到新项目时,它会清除旧项目并在收到的 ObservableList 中添加 OnListChangedCallback 以处理微更改
  5. 如果 ObservableList 有任何变化,MyAdapter 将相应地改变而不完全刷新
  6. 如果我想显示一组完全不同的相同项目类型,我可以重新设置 binding 变量,这样 BindingAdapter 将再次调用 MyAdapter 项目将完全改变。

例如,如果我想显示 Game 类型的项目,我有两个不同的列表:"owned games" 和 "wishlist games",我可以调用 binding.setItems(whateverItems)完全刷新显示的项目,但是例如,如果我在列表中移动 "wishlist games" 以按相关性组织它们,则只会在每个列表中执行微更改,而不会刷新整个内容。

事实证明这个想法是不可行的,因为每次对 ObservableList 进行一次更改时,数据绑定都会重新执行 BindingAdapter,因此例如我观察到休闲行为:

  1. 我从一个空的开始 MyAdapter
  2. 当我的项目从我的 API 中获取时,我实例化一个 ObservableArrayList 包装它们并将其传递给 binding
  3. 数据绑定调用我的 BindingAdapter 将项目传递给 MyAdapter
  4. MyAdapter 收到新项目时,它会清除旧项目并在收到的 ObservableList 中添加 OnListChangedCallback 以处理微更改
  5. 如果 ObservableList 中有任何变化,将再次调用 BindingAdapter,因此 MyAdapter 再次接收整个列表并完全刷新。

这种行为对我来说似乎很糟糕,因为它阻止了 ObservableList 在数据绑定 xml 中可用。我无法认真地找出这种行为是可取的合法案例。

我查了一些例子:here and

在第一个 link 中,所有示例都直接使用 ObservableListAdapter,甚至没有传递表单 xml 和实际数据绑定,而在代码中 linked 在 SO 答案中,开发人员基本上做了我尝试做的同样的事情,添加:

if (this.items == items){
        return;
}

在他的开头 Adapter.setItems(ObservableList<T> items) 丢弃所有由于 ObservableList.

中的简单更改而调用该方法的情况

这种行为的必要性是什么?在某些情况下,这种行为是可取的?我觉得 ObservableList 是一个添加了数据绑定的功能,并且非常有用,除非与实际数据绑定一起使用,在这种情况下,它会迫使您抵御它的行为。 如果我在 xml 数据标签和 BindingAdapter 签名中将它声明为简单的 List,那么我可以将它转换回 MyAdapter 中的 ObservableList 并且它工作得很好,但这是一个非常糟糕的黑客攻击。 如果它只是一个独立于数据绑定的功能,而不在每次更改时触发绑定,在我看来会好得多。

根据文档 https://developer.android.com/topic/libraries/data-binding/index.html#observable_collections 中提供的示例,ObservableList 用于使用键整数访问它的项目,即:

<data>
    <import type="android.databinding.ObservableList"/>
    <import type="com.example.my.app.Fields"/>
    <variable name="user" type="ObservableList&lt;Object&gt;"/>
</data>
…
<TextView
   android:text='@{user[Fields.LAST_NAME]}'
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

因此,当 ObservableList 内部发生更改时,它会触发 BindingAdapter 更新 UI。我认为这是在 DataBinding 处于开发状态时暂时使用 ObservableList 的主要目的。也许将来 DataBinding 会更新为一个新的 SomeObservableList,它将用于 RecyclerView。 同时,您可以使用 if (this.items == items){return;} 如果它适合您,或者重新考虑您使用 ObservableList.

的逻辑