Skip to content

Instantly share code, notes, and snippets.

@pasmat
Created August 22, 2018 14:25
Show Gist options
  • Save pasmat/f1f8f04eeab4dde7dc9b534a51f67d15 to your computer and use it in GitHub Desktop.
Save pasmat/f1f8f04eeab4dde7dc9b534a51f67d15 to your computer and use it in GitHub Desktop.
Data-binded values that are boxed(such as ones that come from Kotlin, as there's no primitive types in Kotlin..) requires safe unboxing, so there's no NPE(null pointer exception) when binding data. Theres a method for this safeUnbox inside Android SDK, however this doesn't support two-way data binding. Therefore we have to define these two-way s…
package fi.matalamaki.util;
import androidx.databinding.InverseMethod;
/**
* Data-binded values that are boxed(such as ones that come from Kotlin,
* as there's no primitive types in Kotlin..) requires safe unboxing,
* so there's no NPE(null pointer exception) when binding data.
*
* Theres a method for this safeUnbox inside Android SDK,
* however this doesn't support two-way data binding.
*
* Therefore we have to define these two-way safe unboxing methods by ourselves.
*
* example usage inside xml
*
*
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
<data>
<import type="fi.matalamaki.util.Boxer"/>
<variable
name="intParameter"
type="java.lang.Integer"/>
</data>
<SeekBar
android:layout_width="match_parent"
android:layout_height="match_parent"
android:progress="@={Boxer.unbox(intParameter)}"/>
</layout>
*
*
*/
public class Boxer {
public static final char DEAULT_CHAR = ' ';
private static final int DEFAULT_NUMBER = 0;
@InverseMethod("boxBoolean")
public static boolean unbox(Boolean b) {
return (b != null) && b;
}
public static Boolean boxBoolean(boolean b) {
return b;
}
@InverseMethod("boxChar")
public static char unbox(Character c) {
return c != null ? c : DEAULT_CHAR;
}
public static Character boxChar(char c) {
return c;
}
@InverseMethod("boxByte")
public static byte unbox(Byte b) {
return b != null ? b : DEFAULT_NUMBER;
}
public static Byte boxByte(byte b) {
return b;
}
@InverseMethod("boxShort")
public static short unbox(Short s) {
return s != null ? s : DEFAULT_NUMBER;
}
public static Short boxShort(short s) {
return s;
}
@InverseMethod("boxInteger")
public static int unbox(Integer i) {
return i != null ? i : DEFAULT_NUMBER;
}
public static Integer boxInteger(int i) {
return i;
}
@InverseMethod("boxInteger")
public static long unbox(Long l) {
return l != null ? l : DEFAULT_NUMBER;
}
public static Long boxLong(long l) {
return l;
}
@InverseMethod("boxFloat")
public static float unbox(Float f) {
return f != null ? f : DEFAULT_NUMBER;
}
public static Float boxFloat(float f) {
return f;
}
@InverseMethod("boxDouble")
public static double unbox(Double d) {
return (d != null) ? d : DEFAULT_NUMBER;
}
public static Double boxDouble(double d) {
return d;
}
}
@wzieba
Copy link

wzieba commented Oct 7, 2018

thanks for snippet 👍

@KStrait
Copy link

KStrait commented Jun 10, 2020

I get cannot generate view binders java.lang.NullPointerException when using this for a checkbox.

<CheckBox android:id="@+id/new_delivery_check" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/margin_small" android:layout_marginTop="@dimen/margin_normal" android:background="@null" android:minWidth="0dp" android:minHeight="0dp" android:checked="@={Unbox.unbox(viewModel.getDeliveryCheck())}" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/quote_name_input" />

Any tips?

@pasmat
Copy link
Author

pasmat commented Jun 12, 2020

I get cannot generate view binders java.lang.NullPointerException when using this for a checkbox.

<CheckBox android:id="@+id/new_delivery_check" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/margin_small" android:layout_marginTop="@dimen/margin_normal" android:background="@null" android:minWidth="0dp" android:minHeight="0dp" android:checked="@={Unbox.unbox(viewModel.getDeliveryCheck())}" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/quote_name_input" />

Any tips?

viewModel must be null in this case, so you'd need to check whether the viewModel is null or make sure the viewModel is never null

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment