1

I have used autogeneration for Parcelable implementation in a Kotlin data class. The same class is used as an Entity in Room so I have default values for every constructor params to provide an empty constructor to Room. When I try to pass this item as Parcelable the app crashes with UnsupportedOperationException and this message

Parcelables don't support default values

The work around for now I have , I just serialize the object with Gson and pass it as String but I would like to know if there is proper way to handle default values in Kotlin and Parcelable.

Here is the class

@Entity
data class ProductData(
    //primary key here
    @ ColumnInfo val alcoholRestriction: Boolean = false,
    @Ignore val averageWeight: Double = 0.0,
    @Ignore val hotFoodRestriction: Boolean = false,
    @Ignore val maxOrderValue: Double = 0.0,
    @Ignore val minOrderValue: Double = 0.0,
    @Ignore val orderIncrement: Double = 0.0,
    @ColumnInfo var productId: String = "",
    @Ignore val stdUomCd: String = "",
    @Ignore val uomQty: String = ""
) : Parcelable {
    constructor(parcel: Parcel) : this(
        parcel.readByte() != 0.toByte(),
        parcel.readDouble(),
        parcel.readByte() != 0.toByte(),
        parcel.readDouble(),
        parcel.readDouble(),
        parcel.readDouble(),
        parcel.readString(),
        parcel.readString(),
        parcel.readString()
    )

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeByte(if (alcoholRestriction) 1 else 0)
        parcel.writeDouble(averageWeight)
        parcel.writeByte(if (hotFoodRestriction) 1 else 0)
        parcel.writeDouble(maxOrderValue)
        parcel.writeDouble(minOrderValue)
        parcel.writeDouble(orderIncrement)
        parcel.writeString(productId)
        parcel.writeString(stdUomCd)
        parcel.writeString(uomQty)
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR : Parcelable.Creator<ProductData> {
        override fun createFromParcel(parcel: Parcel): ProductData {
            return ProductData(parcel)
        }

        override fun newArray(size: Int): Array<ProductData?> {
            return arrayOfNulls(size)
        }
    }


}

Trying to pass is in a bundle and the crash happens on this line.

findNavController().navigate(
            Uri.parse("android-app://androidx.navigation/productDetails/$item"))

it is set in the nav graph as custom Parcelable variable

Rainmaker
  • 10,294
  • 9
  • 54
  • 89

1 Answers1

0

Move your defaults to the constructor, they are mostly useless anyway. Boolean defaults to false and doubles to zero. Only the strings need something.

Also, why make the strings nullable if you assign a default value anyway.

@Entity
data class ProductData(
//primary key here
@ ColumnInfo val alcoholRestriction: Boolean,
@Ignore val averageWeight: Double,
@Ignore val hotFoodRestriction: Boolean,
@Ignore val maxOrderValue: Double,
@Ignore val minOrderValue: Double,
@Ignore val orderIncrement: Double,
@ColumnInfo var productId: String,
@Ignore val stdUomCd: String?,
@Ignore val uomQty: String?
) : Parcelable {
constructor(parcel: Parcel) : this(
    parcel.readByte() != 0.toByte() ?: false,
    parcel.readDouble() ?: 0.0,
    parcel.readByte() != 0.toByte() ?: false,
    parcel.readDouble() ?: 0.0,
    parcel.readDouble() ?: 0.0,
    parcel.readDouble() ?: 0.0,
    parcel.readString() ?: "", 
    parcel.readString() ?: "",
    parcel.readString() ?: ""
)

constructor() : this(
   false, 
   0.0,
   false,
   0.0,
   0.0,
   0.0,
   "",
   "",
   "")

override fun writeToParcel(parcel: Parcel, flags: Int) {
    parcel.writeByte(if (alcoholRestriction) 1 else 0)
    parcel.writeDouble(averageWeight)
    parcel.writeByte(if (hotFoodRestriction) 1 else 0)
    parcel.writeDouble(maxOrderValue)
    parcel.writeDouble(minOrderValue)
    parcel.writeDouble(orderIncrement)
    parcel.writeString(productId)
    parcel.writeString(stdUomCd)
    parcel.writeString(uomQty)
}
Cory Roy
  • 5,379
  • 2
  • 28
  • 47
  • then I will not be able to use this class as an entity in Room, it requires an empty constructor and Boolean will not default to false in the constructor unless you assign the default value to it, Room will complain with the compile error as described here https://stackoverflow.com/questions/44485631/room-persistence-errorentities-and-pojos-must-have-a-usable-public-constructor – Rainmaker Aug 07 '19 at 19:55
  • for the nullable Strings I just added the defaults and didn't refactor yet – Rainmaker Aug 07 '19 at 19:56
  • @Rainmaker Just add an empty constructor. I updated the example – Cory Roy Aug 08 '19 at 18:54