safeUnbox()不能被反转

时间:2017-11-16 16:48:08

标签: android warnings android-databinding

我试图消除我的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包。

4 个答案:

答案 0 :(得分:9)

我没有以这种特殊方式使用Android架构组件或数据绑定库,但我认为我仍然可以提供帮助。

在你的XML中,你已经得到了这个:

android:checked="@={viewModel.value}"

系统会向您发出警告,因为它希望您知道在viewModel.valuenull的情况下,它会做一些特别的事情(表现得像{相反,大概是{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);
}

此解决方案可以复制到任何属性,例如visibilityenabled等,也可以复制到IntegerFloat等任何盒装基元。

如果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,您应该自行定义一个静态函数来安全取消装箱。