Dam*_*tla 33 android android-layout android-databinding
我想设置背景颜色或null使用DataBinding库在我的视图上,但我尝试运行它时遇到异常.
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.Integer.intValue()' on a null object reference
Run Code Online (Sandbox Code Playgroud)
我是这样做的:
android:background="@{article.sponsored ? @color/sponsored_article_background : null}"
Run Code Online (Sandbox Code Playgroud)
我也试过设置转换但它没有用.
@BindingConversion
public static ColorDrawable convertColorToDrawable(int color) {
return new ColorDrawable(color);
}
Run Code Online (Sandbox Code Playgroud)
最后,我使用解决方法解决了它,@BindingAdapter但我想知道如何正确地做到这一点.
Mac*_*ęga 64
首先要知道的是DataBinding库已经提供了一个convertColorToDrawable绑定转换器android.databinding.adapters.Converters.convertColorToDrawable(int).
使用android:background应该"理论上"工作,因为它有相应的setBackground(Drawable)方法.问题是,它看到您尝试将颜色作为第一个参数传递,因此它尝试在将此转换器应用于setBackground(Drawable)方法之前启动它.如果数据绑定决定使用转换器,它将在两个参数上使用它,所以null在将最终结果应用于setter之前也是如此.
因为null不能成为int(并且你不能intValue()在它上面调用)它会抛出NullPointerException.
有人提到官方数据绑定指南中不支持混合参数类型.
以下是此问题的两种解决方案.虽然您可以使用这两种解决方案中的任何一种,但第一种解决方案更容易.
1.可以画画
如果您不是将颜色定义为颜色,而是将其定义为资源中的可绘制颜色(可以在我们的colors.xml文件中:
<drawable name="sponsored_article_background">#your_color</drawable>
Run Code Online (Sandbox Code Playgroud)
要么
<drawable name="sponsored_article_background">@color/sponsored_article_background</drawable>
Run Code Online (Sandbox Code Playgroud)
然后你应该能够android:background像你原来想要的那样使用但是提供可绘制而不是颜色:
android:background="@{article.sponsored ? @drawable/sponsored_article_background : null}"
Run Code Online (Sandbox Code Playgroud)
这里的参数有兼容的类型:first is Drawable和second是null所以它也可以强制转换为a Drawable.
2.作为资源ID
app:backgroundResource="@{article.sponsored ? R.color.sponsored_article_background : 0}"
Run Code Online (Sandbox Code Playgroud)
但它还需要在data部分中添加您的R类导入:
<data>
<import type="com.example.package.R" />
<variable ... />
</data>
Run Code Online (Sandbox Code Playgroud)
将0作为"空资源id"传递是安全的,因为检查setBackgroundResource方法View是否resid不同于0并且将null设置为背景drawable否则.这里没有创建不必要的透明可绘制对象.
public void setBackgroundResource(int resid) {
if (resid != 0 && resid == mBackgroundResource) {
return;
}
Drawable d= null;
if (resid != 0) {
d = mResources.getDrawable(resid);
}
setBackgroundDrawable(d);
mBackgroundResource = resid;
}
Run Code Online (Sandbox Code Playgroud)
pRa*_*NaY 11
我认为你必须尝试默认color而不是null
像这样
android:background="@{article.sponsored ? @color/sponsored_article_background : @color/your_default_color}"
Run Code Online (Sandbox Code Playgroud)
您可以使用的一种方法是编写自定义@BindingConversion以便为您处理:
@BindingConversion
public static ColorDrawable convertColorToDrawable(int color) {
return color != 0 ? new ColorDrawable(color) : null;
}
Run Code Online (Sandbox Code Playgroud)
使用此功能,您可以将任何接受a的属性设置ColorDrawable为整数颜色值(如0或@android:color/transparent),并将其自动转换为轻量级@null.
(即使内置convertColorToDrawable(int)转换器总是创建一个ColorDrawable对象,即使颜色是透明的.)
注意:为了使用此方法代替内置函数@BindingConversion,它必须返回a ColorDrawable而不是a Drawable- 否则内置方法将被视为更具体/适当.
另一种方法是使用静态方法将颜色转换为Drawable数据绑定表达式中的颜色,以使值类型匹配.例如,您可以导入内置Converters类:
<data>
<import type="android.databinding.adapters.Converters"/>
</data>
Run Code Online (Sandbox Code Playgroud)
...并写下你的表达式:
android:background="@{article.sponsored ? Converters.convertColorToDrawable(@color/sponsored_article_background) : null}"
Run Code Online (Sandbox Code Playgroud)
...虽然我个人建议在数据绑定适配器方法中使用这种条件逻辑,例如使用getArticleBackground()返回Drawable或null的方法.通常情况下,如果您避免在布局文件中放置决策逻辑,则更容易调试和跟踪.