Android 绑定适配器在相同的视图类型上使用相同的绑定名称但用于不同的目的

Android Binding Adapter using same binding name on same View type but for different purpose

首先,我是数据绑定的新手,所以请不要因为我的(可能是愚蠢的)问题来评判我:)。我想使用相同的绑定名称,例如 app:dataRecyclerView,并将其绑定到 ViewModel 字段,该字段提供 List<MyModel>。但是,我想为 RecyclerView.

的不同实例使用不同的适配器(例如,为不同的项目布局充气)
// For RecyclerView 1
@BindingAdapter("app:data")
fun setData(recyclerView: RecyclerView, data: List<MyModel>?) {
    data?.let {
        recyclerView.adapter = RV1Adapter(data)
    }
}

// For RecyclerView 2
@BindingAdapter("app:data")
fun setData(recyclerView: RecyclerView, data: List<MyModel>?) {
    data?.let {
        recyclerView.adapter = RV2Adapter(data)
    }
}

在布局上,例如

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/rcv1"
    android:layout_width="match_parent"
    android:layout_height="300dp"
    app:data="${viewModel.data}"/>


<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/rcv2"
    android:layout_width="match_parent"
    android:layout_height="300dp"
    app:data="${viewModel.data}"/>

我怎样才能做到这一点?

我应该使用不同的绑定名称吗? (我以前没有使用这种方法,因为我认为它会有点乱)

或者 'correct' 如何做到这一点?

谢谢

我从未应用过您的解决方案。我一般在Fragment中为ViewModel的数据创建一个观察者,然后传给Adapter。

但我认为我们仍然可以解决您的问题。我不知道你是如何实现你的适配器的。我假设您的适配器是从 ListAdapter 扩展而来的。 因此,我们不会在 Binding Adapter 中初始化您的适配器,而是在 Fragment 中对其进行初始化并将其分配给 Recyclerview。像这样:

// onCreateView method 
val adapter = RV2Adapter()
dataBinding.rcv.adapter = adapter 

然后在绑定适配器中,我们将这样做:

@BindingAdapter("app:data")
fun setData(recyclerView: RecyclerView, data: List<MyModel>?) {
    data?.let {
        recyclerView.adapter.submitList(data)
    }
}

如果您的适配器不是从 ListAdapter 扩展的。您可以在其中创建一个 setter 方法并传递数据列表。

@BindingAdapter("app:data")
    fun setData(recyclerView: RecyclerView, data: List<MyModel>?) {
        data?.let {
            recyclerView.adapter.setData(data)
            recyclerView.adapter.notifyDataChanged()
        }
    }

您不能使用相同的绑定适配器标记,因为两种 setData() 方法具有相同的 signature/parameters,因此在布局中它无法决定使用哪一个。

但是您可以使用单一方法,并且 RecyclerViews 与它们的 id

之间存在差异
@BindingAdapter("app:data")
fun setData(recyclerView: RecyclerView, data: List<MyModel>?) {
    data?.let {
        if (recyclerView.id == R.id.rcv1)
            recyclerView.adapter = RV1Adapter(data)

        else if (recyclerView.id == R.id.rcv2)
            recyclerView.adapter = RV2Adapter(data)
    }
}