gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-29 02:34:44 26 4
gpt4 key购买 nike

匹配ObservableList<Subclass>@BindingAdapterObservableList<Baseclass> 声明行为怪异。


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

设置:

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

我想绑定(bind)一个 android.databinding.ObservableList<Model>RecyclerView通过使用获取列表的自定义绑定(bind)适配器,将其包装成通用的 RecyclerView.Adapter并将其分配给 RecyclerView .

我的绑定(bind)适配器是这样设置的:

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

我的 View 模型具有以下属性:

public final ObservableList<Repo> repos = new ObservableArrayList<>();

Repo在这种情况下实现接口(interface) 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 的有效替代品在绑定(bind)转换器声明中。奇怪,但确实如此 - 如果我将声明更改为使用 ObservableList<Repo> items代码编译正常并且可以工作。但这对我来说不是一个可行的解决方案,因为这会迫使我为我打算使用的每个模型或 View 模型类型编写一个绑定(bind)适配器。所以经过一些试验,我找到了一个不同的解决方案:

    <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解决问题?
  • 因为这对我来说看起来像是一个丑陋的 hack - 实现此行为的正确方法是什么?

附言:

有关该问题的更多背景信息,我基本上是通过这个示例代码来工作的,我发现它是一个很好的灵感来源:https://github.com/manas-chaudhari/android-mvvm/blob/master/Documentation/GettingStarted.md

但是请注意作者是如何厚颜无耻地将他所有的模型对象“转换”为基类类型以避免这个确切的问题here .

最佳答案

那是因为 List在 Java 中不是协变的。这意味着 List<Subclass>不是 List<Baseclass>所以绑定(bind)引擎没有理由考虑你的适配器。你需要:

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

和泛型一直向下。

关于java - BindingAdapter 未被识别为适用于具有泛型的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47695152/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com