我试图消除我的Android应用程序的所有警告,其中一个就是:
viewModel.value是一个盒装字段,但需要取消装箱才能执行android:checked。这可能会导致NPE,因此数据绑定将安全地取消它。您可以更改表达式并使用safeUnbox()显式包装viewModel.value以防止警告
其中value是来自超类的通用ObservableField
:
public abstract class BaseDataTypeViewModel<T> extends BaseObservable {
public final ObservableField<T> value = new ObservableField<>();
...
}
并且作为Boolean
public class CheckBooleanDataTypeViewModel extends BaseDataTypeViewModel<Boolean> {
...
}
我在data binding - safeUnbox warning看到警告发生,因为这是Boolean
而不是boolean
,所以我尝试添加:android:checked="@={safeUnbox(viewModel.value)}"
而不是{{1}但是我得到一个错误,说我无法反转android:checked="@={viewModel.value}"
方法。
**** /数据绑定错误**** msg:表达式android.databinding.DynamicUtil.safeUnbox(viewModelValue)无法反转:方法safeUnbox没有反转,必须将@InverseMethod注释添加到指示在双向绑定表达式中使用哪种方法时使用的方法
我理解正确的2个问题,但是我必须忍受警告以避免错误,或者他们是避免警告和错误的解决方案吗?它所谈论的safeUnbox()
怎么样?我没有设法添加此注释,因为该方法来自android包。
答案 0 :(得分:9)
我没有以这种特殊方式使用Android架构组件或数据绑定库,但我认为我仍然可以提供帮助。
在你的XML中,你已经得到了这个:
android:checked="@={viewModel.value}"
系统会向您发出警告,因为它希望您知道在viewModel.value
为null
的情况下,它会做一些特别的事情(表现得像{相反,大概是{1}}。它通过false
方法完成此操作。
要解决警告,建议明确safeUnbox()
来电。你不能这样做,因为没有&#34;反向&#34;从safeUnbox()
到safeUnbox()
,boolean
将返回。
但听起来你不得不使用Boolean
;您可以创建自己的方法,将safeUnbox()
转换为Boolean
,然后您可以使用建议的注释来声明哪个方法将从boolean
转换回boolean
。
Boolean
现在您可以将XML更改为:
public class MyConversions {
@InverseMethod("myBox")
public static boolean myUnbox(Boolean b) {
return (b != null) && b.booleanValue();
}
public static Boolean myBox(boolean b) {
return b ? Boolean.TRUE : Boolean.FALSE;
}
}
我希望这会有所帮助。如果事实证明我离开了基地,请告诉我;我希望更多地了解这个话题。
我从https://medium.com/google-developers/android-data-binding-inverse-functions-95aab4b11873
中学到的答案中的大部分内容答案 1 :(得分:4)
遇到此问题并找到了更简单的解决方案。您可以通过为盒装类型创建自定义BindingAdapter来避免此警告,如下所示:
@BindingAdapter("android:checked")
public static void setChecked(CompoundButton checkableView, Boolean isChecked) {
checkableView.setChecked(isChecked != null ? isChecked : false);
}
此解决方案可以复制到任何属性,例如visibility
,enabled
等,也可以复制到Integer
,Float
等任何盒装基元。
如果LiveData
值为null
,您还可以提供要使用的值:
@BindingAdapter(value={"android:checked", "nullValue"}, requireAll=false)
public static void setChecked(CompoundButton checkableView, Boolean isChecked, boolean nullValue) {
checkableView.setChecked(isChecked != null ? isChecked : nullValue);
}
并称之为:
<CheckBox
...
android:checked='@{viewModel.value}'
app:nullValue="@{false}"
/>
答案 2 :(得分:0)
在xml中这样做。最后一行代码是最重要的。
<layout>
<data>
<import type="android.view.View"/>
<variable name="entryViewModel"
type="com.craiovadata.groupmap.viewmodel.EntryViewModel" />
</data>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="@{safeUnbox(entryViewModel.showBtnMyGroups) ? View.VISIBLE : View.GONE, default = gone}" />
答案 3 :(得分:0)
我找到了一个代码,此 safeUnbox 实现。
/** @hide */
protected static int safeUnbox(java.lang.Integer boxed) {
return boxed == null ? 0 : (int)boxed;
}
/** @hide */
protected static long safeUnbox(java.lang.Long boxed) {
return boxed == null ? 0L : (long)boxed;
}
/** @hide */
protected static short safeUnbox(java.lang.Short boxed) {
return boxed == null ? 0 : (short)boxed;
}
/** @hide */
protected static byte safeUnbox(java.lang.Byte boxed) {
return boxed == null ? 0 : (byte)boxed;
}
/** @hide */
protected static char safeUnbox(java.lang.Character boxed) {
return boxed == null ? '\u0000' : (char)boxed;
}
/** @hide */
protected static double safeUnbox(java.lang.Double boxed) {
return boxed == null ? 0.0 : (double)boxed;
}
/** @hide */
protected static float safeUnbox(java.lang.Float boxed) {
return boxed == null ? 0f : (float)boxed;
}
/** @hide */
protected static boolean safeUnbox(java.lang.Boolean boxed) {
return boxed == null ? false : (boolean)boxed;
}
因此,如果您的值不是基本类型,则不能直接使用safeUnbox,您应该自行定义一个静态函数来安全取消装箱。