Kotlin Android

Я использовал автоматически сгенерированную функцию плагина Android для Android Studio, и он сгенерировал мне следующий код, но я не могу понять, зачем нужно поле final val для CREATOR? Я впервые вижу ключевое слово 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)
            }
        }
    }
}

person ashur    schedule 22.05.2016    source источник


Ответы (3)


В Kotlin классы и члены являются окончательными по умолчанию. Другими словами, следующие объявления имеют одинаковый байт-код:

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

Таким образом, хотя сгенерированный код имеет ключевое слово 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
}

Хотя создание public static поля final в Java является хорошей практикой, нет строгих требований к Parccelable.Creator поле, которое будет помечено как таковое:

Классы, реализующие интерфейс Parcelable, также должны иметь ненулевое статическое поле CREATOR типа, реализующего интерфейс Parcelable.Creator.

person miensol    schedule 22.05.2016

В Kotlin вы можете использовать расширение @Parcelize Kotlin для Android:

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

Это подключаемый модуль компилятора, который автоматически создает для вас реализацию Parcelable.

Эта страница документации Kotlin содержит более подробную информацию о это, включая требования, поддерживаемые типы и как создать пользовательские посылки для неподдерживаемых типов.


Если вам любопытно и вы хотите погрузиться в технические детали реализации, см. Kotlin Evolution and Enhancement Process Расширение компилятора для поддержки android.os.Parcelable.


Эта функция была экспериментальной до Kotlin 1.3.40< /а>. Если вы все еще используете версию Kotlin до 1.3.40, вам необходимо включить экспериментальные функции, чтобы использовать это:

android {
    // Enable @Parcelize
    // You only need this for Kotlin < 1.3.40
    androidExtensions {
        experimental = true
    }
    ...
}
person Albert Vila Calvo    schedule 03.05.2019

Используйте аннотацию @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, "[email protected]")

   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
    }
    ...
}
person Shihab Uddin    schedule 11.03.2020