Kotlin安卓可序列化对象Parcelable

9

我使用了Android Studio的自动生成功能,生成了以下代码,但是我不理解为什么需要在CREATOR字段上加上final val关键字?我第一次在Kotlin中看到final关键字。

data class Person(
        val name: String,
        val surname: String
) : Parcelable {
    constructor(source: Parcel): this(source.readString(), source.readString())

    override fun describeContents(): Int {
        return 0
    }

    override fun writeToParcel(dest: Parcel?, flags: Int) {
        dest?.writeString(name)
        dest?.writeString(surname)
    }

    companion object {
        @JvmField final val CREATOR: Parcelable.Creator<Person> = object : Parcelable.Creator<Person> {
            override fun createFromParcel(source: Parcel): Person {
                return Person(source)
            }

            override fun newArray(size: Int): Array<Person?> {
                return arrayOfNulls(size)
            }
        }
    }
}
4个回答

9
在 Kotlin 中,默认情况下 类和成员都是 final 的。换句话说,以下声明具有相同的字节码:
@JvmField final val CREATOR: Parcelable.Creator<Person> = PersonCreator()
@JvmField val CREATOR: Parcelable.Creator<Person> = PersonCreator()

因此,尽管生成的代码具有“final”关键字并且不会出现错误,但它是多余的。
尽管默认情况下类和成员都是final的,但在Kotlin中仍然需要final修饰符。一个例子是在派生类中将“open”方法标记为“final”:
open class Base {
    open fun test(){}
}

open class DerivedA : Base(){
    final override fun test(){}
}

class DerivedB : DerivedA() {
    override fun test(){} //error: 'test' in 'DerivedA' is final and cannot be overriden
}

在Java中,将public static字段标记为final是一个好习惯,但不需要严格要求Parccelable.Creator字段也要这样做:

实现Parcelable接口的类还必须有一个非空的静态字段,称为CREATOR,其类型实现了Parcelable.Creator接口。


7
在 Kotlin 中,您可以使用 @Parcelize Kotlin Android 扩展功能:
@Parcelize
data class User(val id: String, val name: String) : Parcelable

这是一个编译器插件,它可以自动生成适用于Parcelable的实现。Kotlin文档的此页面提供了更多有关此插件的详细信息,包括要求、支持的类型以及如何为不受支持的类型创建自定义parceler
如果您想深入了解其技术实现细节,请参见Kotlin演化和增强过程中的编译器扩展以支持android.os.Parcelable
此功能在Kotlin 1.3.40之前是实验性的。如果您仍在使用比1.3.40更早版本的Kotlin,则需要启用实验性功能才能使用它。
android {
    // Enable @Parcelize
    // You only need this for Kotlin < 1.3.40
    androidExtensions {
        experimental = true
    }
    ...
}

2
使用 @Parcelize 注释来标记数据类,并继承 Parcelable。Kotlin 会自动处理其余部分。例如,Person 数据类。
@Parcelize
data class Person(val name: String, val age: Int, val email: String) : Parcelable

您可以在活动中按以下方式点击按钮发送值。
   private val PERSON = "person"

   // first ensure a person object with data
   val person = Person("Shihab Uddin", 30, "shihab.mi7@gmai.com")

   binding.buttonSend.setOnClickListener {

        val intent = Intent(this, ReceiveParcelableAcitivty::class.java)
        //then put an parcelable extra to intent 
        intent.putExtra(PERSON, person)
        startActivity(intent)

    }

接收者活动将获取类似以下数据的信息:
    private val PERSON = "person"
    intent?.let {
        var person = intent.extras.getParcelable(PERSON) as Person
        bind.textViewData.text = " Data Receive: $person"
    }

androidExtensions属性在kotlin 1.3.40中不再是必需的。

android {

    // You only need this for Kotlin < 1.3.40
    androidExtensions {
        experimental = true
    }
    ...
}

0
在最新的Kotlin和Gradle版本中(抱歉,我忘记了版本号),你需要添加
plugins {
     id("kotlin-parcelize")
}

在这个文件中 build.gradle.kts(取决于你的gradle是kotlin还是其他语言)
现在,你可以使用它了。
import kotlinx.parcelize.Parcelize

@Parcelize
data class User(val id: String, val name: String) : Parcelable

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接