简述
java.lang.IllegalStateException: Required DataBindingComponent is null in class ActivityDatabindingBaseBindingImpl. A BindingAdapter in com.zxf.jetpackrelated.databinding.simpleUse.ImageViewAdapter is not static and requires an object to use, retrieved from the DataBindingComponent. If you don’t use an inflation method taking a DataBindingComponent, use DataBindingUtil.setDefaultComponent or make all BindingAdapter methods static.
简单理解一下,用BindingAdapter修饰的方法不是静态方法。但是需要是静态方法。
问题原因分析
猜测,你应该是以下两种写法之一😂
-
class ImageViewAdapter{ companion object{ @BindingAdapter("image") fun setImage(imageView: ImageView, imageUrl: String?) { if (imageUrl.isNotNullOrEmpty()) { Glide.with(imageView) .load(imageUrl) .into(imageView) } else { imageView.setBackgroundColor(Color.BLUE) } } } }
-
object ImageViewAdapter{ @BindingAdapter("image") fun setImage(imageView: ImageView, imageUrl: String?) { if (imageUrl.isNotNullOrEmpty()) { Glide.with(imageView) .load(imageUrl) .into(imageView) } else { imageView.setBackgroundColor(Color.BLUE) } } }
虽然以上两种写法在使用上和静态方法差不多,但在运行时它们任然是真正对象的成员实例;可以简单看一下第一种写法生成的java代码的样子
public final class ImageViewAdapter {
@NotNull
public static final ImageViewAdapter.Companion Companion = new ImageViewAdapter.Companion((DefaultConstructorMarker)null);
public static final class Companion {
@BindingAdapter({"image"})
public final void setImage(@NotNull ImageView imageView, @Nullable String imageUrl) {
Intrinsics.checkNotNullParameter(imageView, "imageView");
if (ExtensionUtilsKt.isNotNullOrEmpty((CharSequence)imageUrl)) {
Intrinsics.checkNotNullExpressionValue(Glide.with((View)imageView).load(imageUrl).into(imageView), "Glide.with(imageView)\n … .into(imageView)");
} else {
imageView.setBackgroundColor(-16776961);
}
}
}
}
其实内部还是非静态的方法调用,只是通过静态字段的初始化,保证了其单例的特性。object
和 这个类似,大家可以自行查看编译后的java代码。
解决
如果非要使用以上的方式,那么需要增加@JvmStatic
注解,这样kotlin在编译为java代码的时候,可以为其生成对应的静态方法。
-
class ImageViewAdapter{ companion object{ @BindingAdapter("image") @JvmStatic fun setImage(imageView: ImageView, imageUrl: String?) { if (imageUrl.isNotNullOrEmpty()) { Glide.with(imageView) .load(imageUrl) .into(imageView) } else { imageView.setBackgroundColor(Color.BLUE) } } } }
-
object ImageViewAdapter{ @BindingAdapter("image") @JvmStatic fun setImage(imageView: ImageView, imageUrl: String?) { if (imageUrl.isNotNullOrEmpty()) { Glide.with(imageView) .load(imageUrl) .into(imageView) } else { imageView.setBackgroundColor(Color.BLUE) } } }
简单看一下反编译之后的代码,kotlin生成了对应的静态方法,调用了产生的伴生对象
public static final void setImage(@NotNull ImageView imageView, @Nullable String imageUrl) {
Companion.setImage(imageView, imageUrl);
}
那有没有不需要增加注解就直接是静态方法的办法呢?当然有,在kotlin里面顶级函数,就对应java的静态函数,所以可以直接这么写:
直接使用顶级函数就可以了,可以看一下,编译后的java代码:
public final class CustomBindingAdapterKt {
@BindingAdapter({"image"})
public static final void setImage(@NotNull ImageView imageView, @Nullable String imageUrl) {
Intrinsics.checkNotNullParameter(imageView, "imageView");
if (ExtensionUtilsKt.isNotNullOrEmpty((CharSequence)imageUrl)) {
Intrinsics.checkNotNullExpressionValue(Glide.with((View)imageView).load(imageUrl).into(imageView), "Glide.with(imageView)\n … .into(imageView)");
} else {
imageView.setBackgroundColor(-16776961);
}
}
}
对应java的类名为文件名+kt
,对应的方法为static final
修饰的方法。
推荐呢还是直接使用顶级函数方便一点。如果使用伴生对象+JvmStatic注解的话,会产生额外的对象。