Search code examples
androidkotlinarraylistparcelable

Getting kotlin.TypeCastException when trying to use parcelable on an ArrayList variable which contains null fields


I literally started yesterday with using Kotlin, so I am still having a hard time understanding the underlying principles. I want to send an object via intent to another activity and implemented parcelable on the object. The object contains some MutableLists in the form of:

var favoritePlaces: MutableList<String?>? = null

I used this method constructor to parcelize it:

constructor(`in`: Parcel) {
  `in`.readList(favoritePlaces, String::class.java.classLoader)
}

This is the error I get in Android Studio since a type mismatch exists:

Android Studio error

I tried to go with the suggestion of Android Studio leaving me with this here in the constructor:

constructor(`in`: Parcel) {
   `in`.readList(favoritePlaces as List<*>, String::class.java.classLoader)
 }

And in the writeToParcel method:

override fun writeToParcel(dest: Parcel, flags: Int) {
    dest.writeList(favoritePlaces as List<*>?)
}

But when I try to use this, then I get the following error message when starting the Activity:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.test.app.Activity}: kotlin.TypeCastException: null cannot be cast to non-null type kotlin.collections.List<*>

I do understand that the type kotlin.collections.List<*> is a non-null type and since I have some null fields in my arrays, it makes sense that this error occurs. My question is now, how can I parcelize String Arrays in Kotlin with non-empty as well as empty fields???


Solution

  • readList expects a non-null argument list to which it will add elements, so you need to initialize it before calling readList:

    favoritePlaces = mutableListOf<String?>()
    `in`.readList(favoritePlaces as List<*>, String::class.java.classLoader)
    

    Or better,

    favoritePlaces = `in`.createStringArrayList()
    

    But in Kotlin there's basically no reason to do this manually; use @Parcelize instead if possible (you'll need to move properties to the primary constructor instead of class body).