alexm
alexm

Reputation: 1315

Creating a Parcelable class with a secondary constructor that takes a list as parameter in Kotlin

I'm getting started with Kotlin and trying to implement a parcelable object that receives a list of strings as parameter of the secondary constructor. However, I'm getting the error:

Cannot access '< this >' before super class constructor has been called

here is my code:

class StringChecker(val stringList : List<String>) : Parcelable {

    var mStringList = stringList

    constructor(parcel: Parcel) : this(parcel.readStringList(mStringList))

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeStringList(mStringList)
    }

    override fun describeContents(): Int {
        return 0
    }

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

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

}

I understand that I cannot call the member variable mStringList before creating the object and that of course makes sense, however the readStringList method requires a string list parameter. How can I resolve this issue? Is this a problem of my design parcelable vs taking list as constructor parameter?

Upvotes: 2

Views: 2110

Answers (2)

lllyct
lllyct

Reputation: 399

You can't use fields in secondary constructor. Use createStringArrayList() instead of readStringList(mStringList)

constructor(parcel: Parcel) : this(parcel.createStringArrayList())

Upvotes: 3

Alexey Romanov
Alexey Romanov

Reputation: 170745

For this specific case, you could write it as

constructor(parcel: Parcel) : this(mutableListOf<String>()) {
  parcel.readStringList(mStringList)
}

But I would prefer just to make it a factory method, not a constructor. Especially since you need it for a factory method anyway. Namely:

companion object CREATOR : Parcelable.Creator<StringChecker> {
    override fun createFromParcel(parcel: Parcel): StringChecker {
        val stringList = mutableListOf<String>()
        parcel.readStringList(stringList)
        return StringChecker(stringList)
    }

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

Some more: you probably don't want to have both stringList and mStringList properties, as your code currently does. If it needs to be var, just do class StringChecker(var stringList : List<String>) instead. Also look at @Parcelize.

Upvotes: 1

Related Questions