Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

Android Kotlin : ParcelableArrayList works for Fragment argument but crashed when used in intent extra

Ask Question

I am trying to pass some data with ParcelableArrayList in my Android app written in Kotlin.

The data class is very simple:

package com.example.testapp
import android.os.Parcel
import android.os.Parcelable
class Data(val name: String, val size: Long): Parcelable {
    override fun writeToParcel(dest: Parcel, flags: Int) {
        dest.writeString(name)
        dest.writeLong(size)
    override fun describeContents(): Int {
        return 0
    companion object {
        val CREATOR = object: Parcelable.Creator<Data> {
            override fun createFromParcel(source: Parcel): Data {
                val name = source.readString()!!
                val size = source.readLong()!!
                return Data(name, size)
            override fun newArray(size: Int) = arrayOfNulls<Data>(size)

When I tried to pass it via fragment transition, it works fine. But it crashed when I put it in the extra of an intent, like this:

val dataArray = arrayListOf<Data>(Data("AAA", 111L), Data("BBB", 222L))
val intent = Intent(this, SecondActivity::class.java)
intent.putParcelableArrayListExtra("DataList", dataArray)
startActivity(intent)

and in the second activity, I am doing as the following to extract the data:

var dataArray = intent?.getParcelableArrayListExtra<Data>("DataList")!!
dataArray.forEach{
    Log.d("XXX", "Get data name=${it.name}, size=${it.size}")

Then I got the infamous crash error:

Caused by: android.os.BadParcelableException: Parcelable protocol requires a Parcelable.Creator object called CREATOR on class com.example.testapp.Data
        at android.os.Parcel.readParcelableCreator(Parcel.java:3063)
        at android.os.Parcel.readParcelable(Parcel.java:2981)
        at android.os.Parcel.readValue(Parcel.java:2883)
        at android.os.Parcel.readListInternal(Parcel.java:3324)
        at android.os.Parcel.readArrayList(Parcel.java:2467)
        at android.os.Parcel.readValue(Parcel.java:2904)
        at android.os.Parcel.readArrayMapInternal(Parcel.java:3261)
        at android.os.BaseBundle.initializeFromParcelLocked(BaseBundle.java:292)
        at android.os.BaseBundle.unparcel(BaseBundle.java:236)
        at android.os.Bundle.getParcelableArrayList(Bundle.java:1005)
        at android.content.Intent.getParcelableArrayListExtra(Intent.java:8605)
        at com.example.testapp.SecondActivity.onCreate(SecondActivity.kt:12)
        at android.app.Activity.performCreate(Activity.java:7981)
        at android.app.Activity.performCreate(Activity.java:7970)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3594) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2146) 
        at android.os.Handler.dispatchMessage(Handler.java:107) 
        at android.os.Looper.loop(Looper.java:237) 
        at android.app.ActivityThread.main(ActivityThread.java:7762) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1047) 

Could anyone please help to point out what am I doing wrong here? I was stuck at this for the whole night!

Thanks a lot.

Try replacing your Data class with the below code

class Data(val name: String, val size: Long): Parcelable {
constructor(parcel: Parcel) : this(
        parcel.readString(),
        parcel.readLong()) {
override fun writeToParcel(parcel: Parcel, flags: Int) {
    parcel.writeString(name)
    parcel.writeLong(size)
override fun describeContents(): Int {
    return 0
companion object CREATOR : Parcelable.Creator<Data> {
    override fun createFromParcel(parcel: Parcel): Data {
        return Data(parcel)
    override fun newArray(size: Int): Array<Data?> {
        return arrayOfNulls(size)
                Thanks, declaring companion object CREATOR works. I wonder why my val CREATOR = object: Parcelable.Creator<Data> works for fragment arguments?
– Robin
                Apr 14, 2020 at 17:01
                Or, you know, @Parcelize class Data(val name: String, val size: Long): Parcelable {}, done.
– Alexey Romanov
                Apr 14, 2020 at 17:19
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.