Kotlin android 可打包

Kotlin android parcelable

我已经为 android studio 使用了 android 插件的自动生成功能,它为我生成了以下代码,但我不明白为什么需要 final val对于 CREATOR 字段?我第一次在 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)
            }
        }
    }
}

在 Kotlin 中 classes and members are final by default。换句话说,以下声明具有相同的字节码:

@JvmField final val CREATOR: Parcelable.Creator<Person> = PersonCreator()
@JvmField val CREATOR: Parcelable.Creator<Person> = PersonCreator()

因此,虽然生成的代码具有 final 关键字并且这不是错误,但它是多余的。

尽管 classes 和成员默认是最终的,但在 Kotlin 中仍然需要 final 修饰符。一个示例是在派生的 class:

中将 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 是一个很好的做法,但是 no strict requirement for the Parccelable.Creator field 可以这样标记:

Classes implementing the Parcelable interface must also have a non-null static field called CREATOR of a type that implements the Parcelable.Creator interface.

在 Kotlin 中,您可以使用 @Parcelize Kotlin Android 扩展:

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

这是一个编译器插件,可以自动为您生成 Parcelable 实现。

This page on the Kotlin docs gives more details about it, including requirements, supported types and how to create custom parcelers 表示不受支持的类型。


如果您好奇并想深入了解实现的技术细节,请参阅 Kotlin 演进和增强过程 Compiler Extension to Support android.os.Parcelable


此功能是 experimental until Kotlin 1.3.40。如果你还在使用 1.3.40 之前的 Kotlin 版本,你需要开启实验性功能才能使用这个:

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

对数据使用@Parcelize 注释 class 并扩展 Parcelable。 Kotlin 会自动为您完成剩下的工作。示例 - 人员数据 class.

@Parcelize
data class Person(val name: String, val age: Int, val email: String) : Parcelable

您可以从 activity.

中发送值,让我们按如下所示的按钮单击
   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)

    }

接收者activity会得到类似

的数据
    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
    }
    ...
}