data binding - safeUnbox warning
AndroidData BindingAndroid Gradle-PluginWarningsAndroid DatabindingAndroid Problem Overview
after i upgrade AS gradle version to 2.3.0, data binding encounter a warning :
> Warning:selectMap[index] is a boxed field but needs to be un-boxed to execute selectMap[index] ? @android:color/white : @android:color/transparent. This may cause NPE so Data Binding will safely unbox it. You can change the expression and explicitly wrap selectMap[index] with safeUnbox() to prevent the warning
selectMap is an ObservableMap, then i search this warning but got just few discussions and did not fix it
Android Studio 2.3.0-alpha1: Databinding + int unboxing causes compile errors
Databinding - data object is null on API 15-18
I follow the way in the links, modify selectMap[index]
to safeUnbox(selectMap[index])
but got syntax error.
So anyone know how to fix this warning?
Edit : Here is the xml file code
<?xml version="1.0" encoding="utf-8"?>
<data class="SupportCountryViewHolderBinding">
<variable
name="viewModel"
type="com.goodarc.care_about.activity.account.support_country.SupportCountryHolderViewModel" />
<variable
name="dataSource"
type="com.goodarc.care_about.module.assets_file.SupportCountry" />
<variable
name="selectMap"
type="android.databinding.ObservableMap<Integer, Boolean>" />
<variable
name="index"
type="int" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@{selectMap[index] ? @android:color/white : @android:color/transparent}"
android:onClick="@{(v) -> viewModel.onItemSelectListener(selectMap, index)}"
android:orientation="vertical"
android:padding="20dp">
<TextView
style="@style/TitleLabel2"
android:layout_gravity="center_vertical|start"
android:text="@{dataSource.display}"
android:textColor="@{selectMap[index] ? @android:color/black : @android:color/white}"
tools:text="Taiwan (+886)" />
</LinearLayout>
Build is succeed, but warning come out(i past above).
Android Solutions
Solution 1 - Android
I had the same warning, in my case changing the variable declaration from Boolean type to boolean type solve the problem:
From:
<variable
name="readOnly"
type="Boolean" />
To:
<variable
name="readOnly"
type="boolean" />
So, maybe you can try with:
<variable
name="selectMap"
type="android.databinding.ObservableMap<Integer, boolean>" />
Solution 2 - Android
You can add safeUnbox like this:
android:text="@{Double.toString(safeUnbox(product.listPrice))}"
Solution 3 - Android
> w: warning: enabled is a boxed field but needs to be un-boxed > to execute android:checked.
This warning comes because enabled field can be null. If you take Boolean
instead of boolean
, so Boolean
can be null. So this warning comes. That this field can make NullPointerException
.
---------------- Case 1 - One Way Binding----------------
<variable
name="enabled"
type="Boolean"/>
....
<Switch
android:checked="@{enabled}"
/>
###Solution 1
<Switch
android:checked="@{safeUnbox(fieldName)}"
/>
###Solution 2
Change Boolean
to primitive type boolean
. So that it never be null, default value of boolean
is false
.
<variable
name="enabled"
type="boolean"/>
---------------- Case 2 - Two-Way Binding----------------
When you have two-way binding, then you can not use safeUnbox()
way, because safeUnbox()
will not be inverted.
<variable
name="enabled"
type="Boolean"/>
....
<Switch
android:checked="@={enabled}"
/>
This will not work now.
<Switch
android:checked="@{safeUnbox(fieldName)}"
/>
###Solution 1
Change Boolean
to primitive type boolean
. So that it never be null, default value of boolean
is false.
<variable
name="enabled"
type="boolean"/>
###Solution 2
A long way is to make inverse binding adapters for safeUnbox. See here.
###What is safeUnbox() method?
safeUnbox()
just check null value and return non-null value. You can see below methods which are defined in Data binding library.
public static int safeUnbox(java.lang.Integer boxed) {
return boxed == null ? 0 : (int)boxed;
}
public static long safeUnbox(java.lang.Long boxed) {
return boxed == null ? 0L : (long)boxed;
}
public static short safeUnbox(java.lang.Short boxed) {
return boxed == null ? 0 : (short)boxed;
}
public static byte safeUnbox(java.lang.Byte boxed) {
return boxed == null ? 0 : (byte)boxed;
}
public static char safeUnbox(java.lang.Character boxed) {
return boxed == null ? '\u0000' : (char)boxed;
}
public static double safeUnbox(java.lang.Double boxed) {
return boxed == null ? 0.0 : (double)boxed;
}
public static float safeUnbox(java.lang.Float boxed) {
return boxed == null ? 0f : (float)boxed;
}
public static boolean safeUnbox(java.lang.Boolean boxed) {
return boxed == null ? false : (boolean)boxed;
}
###I explained about Boolean, this solution is same for Integer
, Double
, Character
etc.
Solution 4 - Android
Instead of ObservableField<T>
you should use special version for the primitives:
ObservableInt
for theint
ObservableBoolean
for theboolean
ObservableFloat
for thefloat
ObservableChar
for thechar
ObservableLong
for thelong
ObservableByte
for thebyte
ObservableShort
for theshort
Solution 5 - Android
I had this warning popup when i did something like :
android:visibility="@{viewmodel.isLoading ? View.INVISIBLE : View.VISIBLE}"
adding safeunbox like so :
android:visibility="@{safeUnbox(viewmodel.isLoading) ? View.INVISIBLE : View.VISIBLE}"
removed the warning after rebuild
Solution 6 - Android
This can appear as well whenever you are using a custom BindingAdapter
so in my case I needed to make the second argument as nullable, and the warning went away.
@BindingAdapter("xyz")
fun xyzAdapter(view: View, value: Int?) {
value?.let {
//TODO
}
}
I am not using Java, but if you are make sure to include @Nullable
annotation, and do a null condition.
Solution 7 - Android
Add the safeUnbox()
to the warning variable will make this warning gone and it will still work well
android:alpha="@{alpha != null ? safeUnbox(alpha) : 0.5f}"