Reputation: 31
I get the Error message "Parcelable protocol requires a Parcelable.Creator object called CREATOR on class .....", but I do have a Creator and I don't know what is wrong with it. I copied it from https://developer.android.com/reference/android/os/Parcelable and changed the class name to fit my code. I suspect that the (automatic) conversion from Java to Kotlin wasn't perfect (or to be precise: did it slightly different than it would be needed), but I don't know what the problem is exactly.
There is a Thread with the same Error Message (Parcelable protocol requires a Parcelable.Creator object called CREATOR (I do have CREATOR)) but the problem there was that "fun writeToParcel" did not write in in the same order as it is read in "fun DataHandler". That is not the Problem in my case as it's in the same order.
Another answer there pointed out that it could be a problem that the function needs to be static. However, Kotlin has no "static" function. I read that it's done with "Companion object". I tried that (see below), but it threw another error - and I'm not sure if it would even work.
class DataHandler : Parcelable {
var player1name = ""
var player1color = 0
//main constructor
fun DataHandler(player1name: String, player1color: Int) {
this.player1name = player1name
this.player1color = player1color
}
//write object values to parcel for storage
override fun writeToParcel(dest: Parcel, flags: Int) {
//write all properties to the parcle
dest.writeString(player1name)
dest.writeInt(player1color)
}
//constructor used for parcel
fun DataHandler(parcel: Parcel) {
//read and set saved values from parcel
player1name = parcel.readString()
player1color = parcel.readInt()
}
//creator - used when un-parceling our parcle (creating the object)
val CREATOR: Parcelable.Creator<DataHandler> = object : Parcelable.Creator<DataHandler> {
override fun createFromParcel(parcel: Parcel): DataHandler {
return DataHandler(parcel) as DataHandler
}
override fun newArray(size: Int): Array<DataHandler?> {
return arrayOfNulls<DataHandler>(size)
}
}
//return hashcode of object
override fun describeContents(): Int {
return hashCode()
}
}
This is the sending activity:
val intentPickPlayer = Intent(this, PlayGame::class.java)
var dataHandler = DataHandler()
dataHandler.player1name = "testing"
intentPickPlayer.putExtra("data", dataHandler)
startActivity(intentPickPlayer)
This is the receiving activity:
class PlayGame : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.playgame)
val test = intent.getParcelableExtra<DataHandler>("data")
Toast.makeText(this, test.player1name, Toast.LENGTH_SHORT).show()
}
Like said above: I tried to make the CREATOR static by putting it into a companion object (apparently that's the way it works in Kotlin, but that produces another error (and I'm not sure if it fixes the first problem)
companion object {
//creator - used when un-parceling our parcle (creating the object)
val CREATOR: Parcelable.Creator<DataHandler> = object : Parcelable.Creator<DataHandler> {
override fun createFromParcel(parcel: Parcel): DataHandler {
//HERE COMES AN ERROR: parcel has a red underlining and it says: "too many Arguments for public constructor DataHandler()
return DataHandler(parcel) as DataHandler
}
override fun newArray(size: Int): Array<DataHandler?> {
return arrayOfNulls<DataHandler>(size)
}
}
Upvotes: 3
Views: 2923
Reputation: 439
In Kotlin constructors are defined by the constructor
keyword - https://kotlinlang.org/docs/reference/classes.html
See also https://kotlinlang.org/docs/reference/classes.html#secondary-constructors for info on secondary constructors. Secondary constructors need to delegate to the primary one.
Default constructors are usually defined after the class name and properties defined as part of it:
class DataHandler(var player1name: String, var player1color: Int) : Parcelable { //write object values to parcel for storage override fun writeToParcel(dest: Parcel, flags: Int) { //write all properties to the parcle dest.writeString(player1name) dest.writeInt(player1color) } //constructor used for parcel constructor(parcel: Parcel) : this( //read and set saved values from parcel player1name = parcel.readString(), player1color = parcel.readInt()) companion object { @JvmField //creator - used when un-parceling our parcle (creating the object) val CREATOR: Parcelable.Creator = object : Parcelable.Creator { override fun createFromParcel(parcel: Parcel): DataHandler { return DataHandler(parcel) as DataHandler } override fun newArray(size: Int): Array { return arrayOfNulls(size) } } } //return hashcode of object override fun describeContents(): Int { return hashCode() } }
Upvotes: 6