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

Posted

技术标签:

【中文标题】“Parcelable 协议需要一个名为 CREATOR 的 Parcelable.Creator 对象”(我确实有 CREATOR)- 在 Kotlin 中【英文标题】:"Parcelable protocol requires a Parcelable.Creator object called CREATOR" (I do have CREATOR) - in Kotlin 【发布时间】:2019-01-17 00:21:17 【问题描述】:

我收到错误消息“Parcelable 协议需要一个 Parcelable.Creator 对象,名为 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)
    

【问题讨论】:

你能试试companion object CREATOR : ... 吗? 既不是:伴生对象 CREATOR : Parcelable.Creator = object : Parcelable.Creator [fun createFromParcel and fun newArray ] 也不是伴生对象 CREATOR :... val CREATOR: Parcelable.Creator = object : Parcelable.Creator [fun createFromParcel and fun newArray ] 工作 This: 伴生对象 CREATOR : Parcelable.Creator [fun createFromParcel and fun newArray] 看起来更好,但在 fun createFromParcel 中,return 语句中的“parcel”用红色下划线 (消息:“公共构造函数 DataHandler 的参数太多” - 我不知道为什么,因为当它不在伴随对象中时,相同的代码没有下划线) 必须@JvmField标记CREATOR 【参考方案1】:

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

另请参阅https://kotlinlang.org/docs/reference/classes.html#secondary-constructors 以获取有关辅助构造函数的信息。辅助构造函数需要委托给主构造函数。

默认构造函数通常在定义为它的一部分的类名和属性之后定义:

类 DataHandler(var player1name: String, var player1color: Int) : Parcelable //将对象值写入parcel进行存储 覆盖有趣的 writeToParcel(dest: Parcel, flags: Int) //将所有属性写入parcle dest.writeString(player1name) dest.writeInt(player1color) //用于包裹的构造函数 构造函数(包裹:包裹):这个( //从包裹中读取并设置保存的值 player1name = parcel.readString(), player1color = parcel.readInt()) 伴随对象 @JvmField //creator - 在解包我们的包裹时使用(创建对象) val 创建者:Parcelable.Creator = 对象:Parcelable.Creator 覆盖乐趣 createFromParcel(parcel: Parcel): DataHandler 返回 DataHandler(parcel) 作为 DataHandler 覆盖有趣的 newArray(size: Int): Array 返回arrayOfNulls(大小) //返回对象的hashcode 覆盖有趣的 describeContents(): Int 返回哈希码()

【讨论】:

? @RaphaelFritz 您能否将此标记为已接受的答案? ***.com/help/someone-answers

以上是关于“Parcelable 协议需要一个名为 CREATOR 的 Parcelable.Creator 对象”(我确实有 CREATOR)- 在 Kotlin 中的主要内容,如果未能解决你的问题,请参考以下文章