0

When I use Intent to pass a Parcelable object from Activity A to Activity B, B activity getExtra is null. Following my code:

class A(var id: Int, var name: String,var bList:MutableList<B>) : Parcelable {
    override fun writeToParcel(p0: Parcel, p1: Int) {
        p0.writeInt(id)
        p0.writeString(name)
        p0.writeTypedList(bList)
    }

    override fun describeContents(): Int {
        return 0
    }

    constructor(parcel: Parcel) : this(
            parcel.readInt(),
            parcel.readString(),
            parcel.createTypedArrayList(B.CREATOR)

    )

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

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

class B

class B(var id: Int, var name: String, var a: A) : Parcelable {
    constructor(parcel: Parcel) : this(
            parcel.readInt(),
            parcel.readString(),
            parcel.readParcelable(A::class.java.classLoader))

    override fun writeToParcel(p0: Parcel, p1: Int) {
        p0.readInt()
        p0.readString()
        p0.readParcelable<A>(A.javaClass.classLoader)
    }

    override fun describeContents(): Int {
        return 0
    }

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

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

I use intent to pass data:

val list = mutableListOf<B>()
val a = A(1,"A",list)
val b1 = B(1,"B1",a)
val b2 = B(2,"B2",a)
list.add(b1)
list.add(b2)
val intent = Intent()
intent.setClass(context, AboutActivity::class.java)
intent.putExtra("frank",a)
startActivity(intent)

I am using following code to retrieve data:

val bundle = intent.extras
val a:A = bundle.getParcelable("frank")

Is this data structure a dead loop when write Parcelable?

Sagar
  • 23,903
  • 4
  • 62
  • 62

1 Answers1

0

There are two issues that you're running into.

First, the writeToParcel() function on class B is reading instead of writing. You most likely meant to do this:

override fun writeToParcel(p0: Parcel, p1: Int) {
    p0.writeInt(id)
    p0.writeString(name)
    p0.writeParcelable(a, 0)
}

Once you make that change, you'll run into the second issue: you'll get a stack overflow error because your models have dependencies on each other. A depends on a list of B objects, each of which has a reference to the A object again. This circular dependency is not a supported by Android's parceling code.

There was a bug ticket opened about this many years ago, but its status is marked as Won't Fix (Infeasible).

There are some workarounds mentioned in another SO post, but in general, it's best to avoid circular dependencies if at all possible.

Dave Leeds
  • 698
  • 6
  • 7
  • Thank you so much, I got the stack overflow error in my project, so I made this test demo to show this issue. I will discuss with backend to change their json structure, and thanks again! – Frank.Wang Apr 23 '18 at 01:56
  • Sounds good, @Frank.Wang! If this answered your question (and it sounds like it did, based on your comment), then please also consider marking it as accepted. – Dave Leeds Apr 23 '18 at 17:08
  • OK, this is my fisrt question on stackoverflow, I will accept.thanks@Dave Leeds – Frank.Wang Apr 24 '18 at 06:18