“可拆分协议需要一个名为CREATOR的Parcelable.Creator对象”(我确实有CREATOR)-在Kotlin中

时间:2018-08-09 13:41:12

标签: android kotlin parcelable parcel companion-object

我收到错误消息“ Parcelable协议需要一个在类.....上称为CREATOR的Parcelable.Creator对象”,但是我确实有一个Creator,但我不知道它有什么问题。我从https://developer.android.com/reference/android/os/Parcelable复制了它,并更改了类名以适合我的代码。 我怀疑从Java到Kotlin的(自动)转换不是完美的(或者确切地说是:它与所需的转换略有不同),但是我不知道到底是什么问题。

有一个具有相同错误消息(Parcelable protocol requires a Parcelable.Creator object called CREATOR (I do have CREATOR))的线程,但是存在的问题是 “ fun writeToParcel”的写入顺序与在“ fun DataHandler”中读取的顺序不同。就我而言,这不是问题,因为顺序相同。

那里的另一个答案指出,该功能需要是静态的可能是一个问题。但是,Kotlin没有“静态”功能。我读到它是用“伴侣对象”完成的。我尝试过(见下文),但是又引发了另一个错误-我不确定它是否还能工作。

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()
    }
}

这是发送活动:

        val intentPickPlayer = Intent(this, PlayGame::class.java)

        var dataHandler = DataHandler()
        dataHandler.player1name = "testing"
        intentPickPlayer.putExtra("data", dataHandler)

        startActivity(intentPickPlayer)

这是接收活动:

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()

}

就像上面说的那样:我试图通过将CREATOR放置到一个伴随对象中来使其静态(显然这是它在Kotlin中的工作方式,但是会产生另一个错误(并且我不确定它是否解决了第一个问题)

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)
    }
}

1 个答案:

答案 0 :(得分:1)

在Kotlin中,构造器由constructor关键字-https://kotlinlang.org/docs/reference/classes.html

定义

有关辅助构造函数的信息,另请参见https://kotlinlang.org/docs/reference/classes.html#secondary-constructors。次要构造函数需要委派给主要构造函数。

默认构造函数通常在类名和属性定义之后定义:

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()
    }
}