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

Rap*_*itz 3 android parcel parcelable kotlin companion-object

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

有一个具有相同错误消息的线程(Parcelable 协议需要一个名为 CREATOR(我确实有 CREATOR)的Parcelable.Creator对象),但问题在于“fun writeToParcel”的写入顺序与读取顺序不同“有趣的数据处理程序”。在我的情况下,这不是问题,因为它的顺序相同。

那里的另一个答案指出,函数需要是静态的可能是一个问题。但是,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()
    }
}
Run Code Online (Sandbox Code Playgroud)

这是发送活动:

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

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

        startActivity(intentPickPlayer)
Run Code Online (Sandbox Code Playgroud)

这是接收活动:

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

}
Run Code Online (Sandbox Code Playgroud)

就像上面说的:我试图通过将 CREATOR 放入一个伴随对象来使 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)
    }
}
Run Code Online (Sandbox Code Playgroud)

小智 5

在 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 {

     //将对象值写入parcel进行存储
    覆盖 fun writeToParcel(dest: Parcel, flags: Int) {
        //将所有属性写入parcle
        dest.writeString(player1name)
        dest.writeInt(player1color)
    }

    //用于包裹的构造函数
    构造函数(包裹:包裹):这个(
        //从parcel中读取并设置保存的值
        player1name = parcel.readString(),
        player1color = parcel.readInt())

    伴生对象{
        @JvmField
        //creator - 在取消包裹我们的包裹时使用(创建对象)
        val CREATOR:Parcelable.Creator = 对象:Parcelable.Creator {

            覆盖乐趣 createFromParcel(parcel: Parcel): DataHandler {
                返回 DataHandler(parcel) 作为 DataHandler
            }

            覆盖 fun newArray(size: Int): Array {
                返回数组空值(大小)
            }
        }
    }

    //返回对象的哈希码
    覆盖 fun describeContents(): Int {
        返回哈希码()
    }
}