BindingAdapter未被识别为适用于具有泛型的属性

时间:2017-12-07 12:26:47

标签: java android mvvm android-databinding

ObservableList<Subclass>@BindingAdapter声明与ObservableList<Baseclass>匹配会以奇怪的方式进行。

我在MVVM的上下文中尝试了android数据绑定库,偶然发现了一个我不理解的行为,到目前为止还没有找到任何资源。

设置:

Min SDK: 19
Target SDK: 26
Build Tools Version: 27.0.1

我希望使用自定义绑定适配器将android.databinding.ObservableList<Model>绑定到RecyclerView,该适配器获取列表,将其包装到通用RecyclerView.Adapter中并将其分配给RecyclerView }。

我的绑定适配器设置如下:

@BindingAdapter({"items"})
public static void bindAdapterWithDefaultBinder(@NonNull RecyclerView recyclerView,
                                                @Nullable ObservableList<Model> items){
... implementation ...
}

我的viewmodel具有以下属性:

public final ObservableList<Repo> repos = new ObservableArrayList<>();
在这种情况下,

Repo实现了接口Model

布局文件包含

<android.support.v7.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:items="@{vm.repos}"
            />

编译时收到以下错误:

Error:Gradle: Execution failed for task ':app:compileDebugJavaWithJavac'.
> java.lang.RuntimeException: Found data binding errors.
  ****/ data binding error ****msg:Cannot find the setter for attribute 'app:items' with parameter type android.databinding.ObservableList<_my-package-name_.Repo> on android.support.v7.widget.RecyclerView.

所以我认为这与Repo类型在绑定转换器声明中未被识别为Model的有效替代有关。奇怪,但确定 - 如果我更改声明使用ObservableList<Repo> items代码编译好并且有效。但这对我来说不是一个可行的解决方案,因为这会迫使我为我打算使用的每个模型或视图模型类型编写绑定适配器。经过一些实验,我发现了一个不同的解决方案:

    <android.support.v7.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:items="@{(Object)vm.repos}"
            />

现在,此解决方案使用ObservableList<Model> items适配器声明进行编译,并在运行时正确传播所有更改事件。所以基本上我将ObservableList<Repo>转换为Object,它被解释为匹配适配器定义。什么?????

请记住,所有这些都发生在编译时,代码生成器已知确切类型,因此不会发生类型擦除。

所以我的问题是:

  • 为什么第一个实现失败了?
  • 为什么要转换为Object解决问题?
  • 因为这看起来像是一个丑陋的黑客 - 实现这种行为的正确方法是什么?

P.S:

关于这个问题的更多上下文,我基本上正在通过这个示例代码,我发现这是一个很好的灵感来源:https://github.com/manas-chaudhari/android-mvvm/blob/master/Documentation/GettingStarted.md

但请注意作者如何厚颜无耻地#34;演员&#34;他的所有模型对象都基类类型,以避免这个确切的问题here

1 个答案:

答案 0 :(得分:0)

我认为您应该这样删除括号:

@BindingAdapter("items")   
public static void bindAdapterWithDefaultBinder(@NonNull RecyclerView recyclerView, @Nullable ObservableList<Model> items) {
... implementation ...
}