safeUnbox() 不能反转
safeUnbox() cannot be inverted
我正在尝试消除我的 Android 应用程序的所有警告,其中之一是:
viewModel.value is a boxed field but needs to be un-boxed to execute android:checked. This may cause NPE so Data Binding will safely unbox it. You can change the expression and explicitly wrap viewModel.value with safeUnbox() to prevent the warning
其中值是来自超级 class 的通用 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)}"
而不是 android:checked="@={viewModel.value}"
但后来我收到一条错误消息,提示我无法反转 safeUnbox()
方法。
****/ data binding error ****msg:The expression android.databinding.DynamicUtil.safeUnbox(viewModelValue) cannot be inverted: There is no inverse for method safeUnbox, you must add an @InverseMethod annotation to the method to indicate which method should be used when using it in two-way binding expressions
我正确理解了这 2 个独立的问题,但我是否必须忍受警告以避免错误,或者它们是否是同时避免警告和错误的解决方案?它所说的 @InverseMethod
呢?我没有设法添加此注释,因为该方法来自 android 包。
我没有以这种特殊方式使用 Android 架构组件或数据绑定库,但我认为我仍然可以提供帮助。
在你的 XML 中,你得到了这个:
android:checked="@={viewModel.value}"
系统给你一个警告是因为它想让你知道在 viewModel.value
是 null
的情况下,它会做一些特别的事情(表现得好像它是 false
相反,大概)。它通过 safeUnbox()
方法实现。
为了解决警告,建议显式调用 safeUnbox()
。你不能那样做,因为 safeUnbox()
中没有 "inverse" 从 boolean
到 Boolean
.[=27= back ]
但听起来你不必使用 safeUnbox()
;您可以创建自己的将 Boolean
转换为 boolean
的方法,然后您可以使用建议的注释来声明哪个方法将从 boolean
转换回 Boolean
。
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;
}
}
现在您可以将 XML 更改为:
android:checked="@={com.example.Whosebug.MyConversions.myUnbox(viewModel.value)}"
希望对您有所帮助。如果事实证明我偏离了基地,请告诉我;我很想了解有关此主题的更多信息。
我在这个答案中的大部分内容都是从 https://medium.com/google-developers/android-data-binding-inverse-functions-95aab4b11873
中学到的
遇到这个问题并找到了更简单的解决方案。您可以通过为这样的盒装类型创建自定义 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}"
/>
在 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}" />
我找到一个代码,这个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,你应该自己定义一个静态函数来安全拆箱。
我正在尝试消除我的 Android 应用程序的所有警告,其中之一是:
viewModel.value is a boxed field but needs to be un-boxed to execute android:checked. This may cause NPE so Data Binding will safely unbox it. You can change the expression and explicitly wrap viewModel.value with safeUnbox() to prevent the warning
其中值是来自超级 class 的通用 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)}"
而不是 android:checked="@={viewModel.value}"
但后来我收到一条错误消息,提示我无法反转 safeUnbox()
方法。
****/ data binding error ****msg:The expression android.databinding.DynamicUtil.safeUnbox(viewModelValue) cannot be inverted: There is no inverse for method safeUnbox, you must add an @InverseMethod annotation to the method to indicate which method should be used when using it in two-way binding expressions
我正确理解了这 2 个独立的问题,但我是否必须忍受警告以避免错误,或者它们是否是同时避免警告和错误的解决方案?它所说的 @InverseMethod
呢?我没有设法添加此注释,因为该方法来自 android 包。
我没有以这种特殊方式使用 Android 架构组件或数据绑定库,但我认为我仍然可以提供帮助。
在你的 XML 中,你得到了这个:
android:checked="@={viewModel.value}"
系统给你一个警告是因为它想让你知道在 viewModel.value
是 null
的情况下,它会做一些特别的事情(表现得好像它是 false
相反,大概)。它通过 safeUnbox()
方法实现。
为了解决警告,建议显式调用 safeUnbox()
。你不能那样做,因为 safeUnbox()
中没有 "inverse" 从 boolean
到 Boolean
.[=27= back ]
但听起来你不必使用 safeUnbox()
;您可以创建自己的将 Boolean
转换为 boolean
的方法,然后您可以使用建议的注释来声明哪个方法将从 boolean
转换回 Boolean
。
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;
}
}
现在您可以将 XML 更改为:
android:checked="@={com.example.Whosebug.MyConversions.myUnbox(viewModel.value)}"
希望对您有所帮助。如果事实证明我偏离了基地,请告诉我;我很想了解有关此主题的更多信息。
我在这个答案中的大部分内容都是从 https://medium.com/google-developers/android-data-binding-inverse-functions-95aab4b11873
中学到的遇到这个问题并找到了更简单的解决方案。您可以通过为这样的盒装类型创建自定义 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}"
/>
在 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}" />
我找到一个代码,这个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,你应该自己定义一个静态函数来安全拆箱。