Search code examples
androidkotlinparcelableparcel

Parcelable not saving variable


I have a data class that implements Parcelable where all its fields are being saved to the Parcel except for a variable outside the constructor.

My class:

data class MyParcelableClass(
    val fieldA: String,
    val fieldB: Int,
    val fieldC: AnotherParcelableClass
) : Parcelable {

    // This is the one I'm having problems with
    var troublesomeVariable: TroublesomeParcelableClass? = null
        set(value) {
            field = value
            if (field != null)
                // do stuff (irrelevant to the question)
        }

    override fun writeToParcel(dest: Parcel?, flags: Int) {
        dest?.run {
            writeString(fieldA)
            writeInt(fieldB)
            writeParcelable(fieldC, flags)
            writeParcelable(troublesomeVariable, flags) 
            /*
             * At this point, troublesomeVariable is null, 
             * even though a value has already been assigned
             */
        }
    }

    override fun describeContents() = 0

    companion object CREATOR : Parcelable.Creator<MyParcelableClass> {
        override fun createFromParcel(source: Parcel): MyParcelableClass {
            val fieldA = source.readString()!!
            val fieldB = source.readInt()
            val fieldC = source.readParcelable<AnotherParcelableClass>(AnotherParcelableClass::class.java.classLoader)!!
            val troublesomeVariable = source.readParcelable<TroublesomeParcelableClass>(TroublesomeParcelableClass::class.java.classLoader)!!
            /*
             * Since troublesomeVariable has been written as null to the parcel,
             * it will obviously be null here as well
             */

            return MyParcelableClass(fieldA, fieldB, fieldC).also {
                it.troublesomeVariable = troublesomeVariable
            }
        }

        override fun newArray(size: Int): Array<MyParcelableClass?> = arrayOfNulls(size)
    }

}

As the comments in the code show, the problem is that the variable is already being written to the parcel as null, even though it already has a value assigned - I put loads of logs and breakpoints to make sure the variable wasn't null before parcelising and indeed it wasn't.

So to sum it all up I'd like to know what I need to do in order to successfully write that variable to the parcel and retrieve it afterwards like the others. Any help will be much appreciated.


Solution

  • Kotlin's data classes have the same behaviour as Java's POJOs: you initialise all the fields in the constructor and have getters (and setters, depending on need).

    When data classes implement Parcelable, only the fields included in the constructor are actually written to and read from the Parcel - I realised it by using the @Parcelize annotation instead of my manual implementation and the IDE shows a hint telling me to annotate troublesomeVariable with @IgnoredOnParcel.

    So the solution was to include troublesomeVariable in the constructor as a private var and manually implement its getter and setter, just like in Java, and it worked.