One of the nice feature of Room is the ability to use an Embedded (store multiple fields as single class variable).
@Entity(tableName = "pin")class Pin ( @PrimaryKey @ColumnInfo(name = "id") @Json(name = "id") var id: String = "", // Must @Embedded be nullable? // If somehow the underlying/saved value (@ColumnInfo) is null, loading/fetch will cause // IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull // https://developer.android.com/reference/android/arch/persistence/room/Embedded // @NonNull doesn't work @Embedded @Json(name = "geo") var location: LocationType? = null ) {}
class LocationType( @ColumnInfo(name = "lat") @Transient var lat: Double? = null, @ColumnInfo(name = "lng") @Transient var lng: Double? = null) { fun isNull(): Boolean { return lat == null || lng == null || (lat == 0.0 && lng == 0.0) }}
Original, I define LocationType
as non nullable value to make checking of null or zero value easier.
@Embedded @Json(name = "geo") var location: LocationType? = null
if (!pin.location.isNull()) { // pin.location != null && !pin.location.isNull() // do something}
Problem arise when the underlying database value of lat
and lng
is null, where LocationType
cannot be initialized and set as null by the generated code, causing IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull
.
I could probably write a converter to convert null to 0 when saving to database, but I doubt this is an good solution.
I decide to make LocationType
nullable instead and assume 0,0
is a valid coordinate (and I won't stupidly convert null to 0 in some unknown cases).
if (pin.location != null) { // do something}