安卓绑定适配器传递多个参数导致错误

46

我对 Android Data Binding 还比较新。我正在按照这个教程学习:Data Binding Library

我想要创建一个接收多个参数的适配器。这是我的代码:

XML

   <ImageView
            android:layout_width="@dimen/place_holder_size"
            android:layout_height="@dimen/place_holder_size"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:layout_centerVertical="true"
            app:url="@{image.imageUrl}"
            app:size="@{@dimen/place_holder_size}"
            />
绑定适配器类
public class ViewBindingAdapters extends BaseObservable {

@BindingAdapter({"bind:url", "bind:size"})
public static void loadImage(ImageView imageView, String url, int size) {
    if (!Strings.isNullOrEmpty(url)) {
        Picasso.with(imageView.getContext()).load(url).resize(size, size).centerCrop().into(imageView);
    }
}
....


}

但是我遇到了这个错误:

java.lang.RuntimeException: 发现数据绑定错误。 ****/ 数据绑定错误 ****msg:在 android.widget.ImageView 上找不到参数类型为 java.lang.String 的属性 'app:url' 的设置器。 文件:... li_image_item.xml 位置:30:27 - 30:40 ****\ 数据绑定错误 ****

有人知道为什么吗?

提前感谢!


image.imageUrl 的数据类型是什么? - Ravi
@pskink,如果您在BindingAdapter中编写bind:urlurl,都可以访问app:url - Ravi
1
在教程中,他们是这样做的,在段落:自定义设置器。 - IrApp
1
没错,'''自定义命名空间在匹配过程中被忽略'''image.imageUrl 是一个字符串吗? - pskink
这个方法以前是这样工作的:@BindingAdapter("imageUrl") public static void loadImage(ImageView imageView, String url) { if (!Strings.isNullOrEmpty(url)) { Picasso.with(imageView.getContext()).load(url).into(imageView); } }。但是现在添加新参数不再起作用了。所以问题不是这个 image.imageUrl。 - IrApp
显示剩余2条评论
6个回答

61

问题在于@dimen/place_holder_size返回float,而您将其捕获为int

将您的BindingAdapter方法更改为此

@BindingAdapter({"bind:url", "bind:size"})
public static void loadImage(ImageView imageView, String url, float size) {

}

您可以参考这个


2
如果我设置了URL值,那么它会调用这个方法,当我设置大小值时,这个方法会再次被调用。有没有办法只在两个值都设置时调用一次? - Usman Rana

25

我做错的是函数参数顺序。你可以在Binding Adapter中添加多个属性,但它们应该与方法中定义的相同顺序的参数匹配

以下是我的Kotlin代码片段:

@BindingAdapter(value = ["bind:brand", "bind:model", "bind:age"], requireAll = false)
@JvmStatic
fun bindProductDetails(linearLayout: LinearLayout, brand: String?, model: String?, age: String?) {
    if (brand != null && !brand.isEmpty()) {
        //code
        //code

    }
}

10

试试这个

 @BindingAdapter(value={"url", "size"}, requireAll=false)
 public static void loadImage(ImageView imageView, String url, int size) {
        if (!Strings.isNullOrEmpty(url)) {
            Picasso.with(imageView.getContext()).load(url).resize(size, size).centerCrop().into(imageView);
        }
    }

只需清理并重新构建项目,因为有时候工作室没有更新,它仍然无法正常工作。尝试使用无效的捕获或重新启动您的IDE(可能很愚蠢,但有时确实有效)。 - Nas

6
除了@Kishan Solanki提供的示例之外,在数据绑定库中发生变化时,您只需要使用逗号分隔的值声明它们即可。例如:
@BindingAdapter("loadImageFrom", "widthDp")
fun loadImages(imageView: ImageView, url: String?, widthDp: Int) {
    url?.let {

        val height = (widthDp / 3) * 4
        val fullUrl = getImagePosterUrl(url)
        Picasso.get().load(fullUrl).resize(widthDp.px, height.px).into(imageView)
    }

}

但最重要的一点是,您需要以DataBinding格式提供数据给适配器属性。

例如,如果您要在XML中作为参数提供Int,您需要编写以下内容:

app:widthDp="@{120}"

这是一个应用程序中的属性,格式为app:your_attribute="@{your_data}"

另外,widthDp.px 是一个扩展函数,它将dp值的Int值转换为基于屏幕密度的相应像素值。不要感到困惑。


5

更新

您无需创建前缀bind:,只需使用此命令即可。

@BindingAdapter({"url", "size"})
public static void loadImage(ImageView imageView, String url, float size) {

}

在xml中可以使用任何前缀,比如app:

app:url="@{image.imageUrl}"

5
请查看 https://developer.android.com/topic/libraries/data-binding/binding-adapters
@BindingAdapter("imageUrl", "placeholder", requireAll = false)
fun ImageView.setImageUrl(url: String?, placeHolder: Drawable?) {
    if (url == null) {
        setImageDrawable(placeholder)
    } else {
        MyImageLoader.loadInto(this, url, placeholder)
    }
}

请注意,BindingAdapter属性和setImageUrl参数可能具有不同的名称,但它们应该按照相同的顺序进行。如果其中一些属性在XML中被定义(在此示例中是ImageView),则会调用此方法。
<ImageView 
    app:imageUrl="@{venue.imageUrl}"
    app:placeholder="@{@drawable/venueError}" />

属性应该与方法中定义的类型相同。您还可以使用监听器。不要使用Kotlin Lambda,而是使用接口

这个类应该放在与XML相同的模块中。否则,您将会得到一个错误,例如AAPT:错误:找不到属性imageUrl(又名com.example.imageUrl)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接