parcelize kotlinx extensions data android parcelable kotlin

android - kotlinx - parcelize kotlin



¿Hay una manera conveniente de crear clases de datos Parcelable en Android con Kotlin? (12)

Actualmente estoy usando el excelente AutoParcel en mi proyecto Java, que facilita la creación de clases Parcelable.

Ahora, Kotlin, que considero para mi próximo proyecto, tiene este concepto de clases de datos, que generan automáticamente los métodos equals, hashCode y toString.

¿Hay una manera conveniente de hacer que una clase de datos de Kotlin sea parcelable de una manera conveniente (sin implementar los métodos manualmente)?


¿Has probado PaperParcel ? Es un procesador de anotaciones que genera automáticamente el código Parcelable Android Parcelable para usted.

Uso:

Anote su clase de datos con @PaperParcel , implemente PaperParcelable y agregue una instancia estática JVM del CREATOR generado, por ejemplo:

@PaperParcel data class Example( val test: Int, ... ) : PaperParcelable { companion object { @JvmField val CREATOR = PaperParcelExample.CREATOR } }

Ahora su clase de datos es Parcelable y se puede pasar directamente a un Bundle o Intent

Editar: actualizar con la última API


Dejaré mi forma de hacerlo en caso de que pueda ayudar a alguien.

Lo que hago es tener un Parcelable genérico

interface DefaultParcelable : Parcelable { override fun describeContents(): Int = 0 companion object { fun <T> generateCreator(create: (source: Parcel) -> T): Parcelable.Creator<T> = object: Parcelable.Creator<T> { override fun createFromParcel(source: Parcel): T = create(source) override fun newArray(size: Int): Array<out T>? = newArray(size) } } } inline fun <reified T> Parcel.read(): T = readValue(T::class.javaClass.classLoader) as T fun Parcel.write(vararg values: Any?) = values.forEach { writeValue(it) }

Y luego creo parcelables como este:

data class MyParcelable(val data1: Data1, val data2: Data2) : DefaultParcelable { override fun writeToParcel(dest: Parcel, flags: Int) { dest.write(data1, data2) } companion object { @JvmField final val CREATOR = DefaultParcelable.generateCreator { MyParcelable(it.read(), it.read()) } } }

Lo que me libra de esa anulación repetitiva.



Kotlin ha hecho que todo el proceso de parcelización en Android sea muy fácil con su anotación @Parcel.

Para hacer eso

Paso 1. Agregue extensiones de Kotlin en su módulo de aplicación gradle

Paso 2. Agregue experimental = verdadero ya que esta característica todavía está en experimentación en gradle.

androidExtensions {experimental = true}

Paso 3. Anona la clase de datos con @Parcel

Here hay un ejemplo simple sobre el uso de @Parcel


La mejor manera sin ningún código repetitivo es el complemento Smuggler Gradle. Todo lo que necesita es simplemente implementar la interfaz AutoParcelable como

data class Person(val name:String, val age:Int): AutoParcelable

Y eso es todo. Funciona para clases selladas también. Además, este complemento proporciona validación en tiempo de compilación para todas las clases autoarcelables.

UPD 17.08.2017 Ahora con Kotlin 1.1.4 y el complemento de extensiones Kotlin para Android , puede usar la anotación @Parcelize . En este caso, el ejemplo anterior se verá así:

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

No es necesario un modificador de data . El mayor inconveniente, por ahora, es usar el complemento kotlin-android-extensiones que tiene muchas otras funciones que podrían ser innecesarias.


Lamentablemente, en Kotlin no hay forma de poner un campo real en una interfaz, por lo que no puede heredarlo de un adaptador de interfaz de forma gratuita: data class Par : MyParcelable

Puede mirar la delegación, pero no ayuda con los campos, AFAIK: https://kotlinlang.org/docs/reference/delegation.html

Entonces, la única opción que veo es una función de estructura para Parcelable.Creator , que es algo obvio.


Puedes probar este complemento:

android-parcelable-intellij-plugin-kotlin

Le ayuda a generar código repetitivo parcelable de Android para la clase de datos de kotlin. Y finalmente se ve así:

data class Model(var test1: Int, var test2: Int): Parcelable { constructor(source: Parcel): this(source.readInt(), source.readInt()) override fun describeContents(): Int { return 0 } override fun writeToParcel(dest: Parcel?, flags: Int) { dest?.writeInt(this.test1) dest?.writeInt(this.test2) } companion object { @JvmField final val CREATOR: Parcelable.Creator<Model> = object : Parcelable.Creator<Model> { override fun createFromParcel(source: Parcel): Model{ return Model(source) } override fun newArray(size: Int): Array<Model?> { return arrayOfNulls(size) } } } }


Simplemente haga clic en la palabra clave de datos de su clase de datos de kotlin, luego presione alt + Enter, seleccione la primera opción que dice "Add Parceable Implementation"


Usando Android Studio y el complemento Kotlin , encontré una manera fácil de convertir mis viejos Parcelable Java Parcelable sin complementos adicionales (si todo lo que quieres es convertir una nueva clase de data en Parcelable , salta al cuarto fragmento de código).

Digamos que tiene una clase Person con toda la placa de caldera Parcelable :

public class Person implements Parcelable{ public static final Creator<Person> CREATOR = new Creator<Person>() { @Override public Person createFromParcel(Parcel in) { return new Person(in); } @Override public Person[] newArray(int size) { return new Person[size]; } }; private final String firstName; private final String lastName; private final int age; public Person(String firstName, String lastName, int age) { this.firstName = firstName; this.lastName = lastName; this.age = age; } protected Person(Parcel in) { firstName = in.readString(); lastName = in.readString(); age = in.readInt(); } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(firstName); dest.writeString(lastName); dest.writeInt(age); } @Override public int describeContents() { return 0; } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public int getAge() { return age; } }

Comience eliminando la implementación Parcelable , dejando un objeto Java simple, simple y Parcelable (las propiedades deben ser finales y establecidas por el constructor):

public class Person { private final String firstName; private final String lastName; private final int age; public Person(String firstName, String lastName, int age) { this.firstName = firstName; this.lastName = lastName; this.age = age; } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public int getAge() { return age; } }

Luego, deje que la opción Code > Convert Java file to Kotlin File haga su magia:

class Person(val firstName: String, val lastName: String, val age: Int)

Convierta esto en una clase de data :

data class Person(val firstName: String, val lastName: String, val age: Int)

Y finalmente, Parcelable esto en Parcelable nuevamente. Desplace el nombre de la clase y Android Studio debería darle la opción de Add Parcelable Implementation . El resultado debería verse así:

data class Person(val firstName: String, val lastName: String, val age: Int) : Parcelable { constructor(parcel: Parcel) : this( parcel.readString(), parcel.readString(), parcel.readInt() ) override fun writeToParcel(parcel: Parcel, flags: Int) { parcel.writeString(firstName) parcel.writeString(lastName) parcel.writeInt(age) } override fun describeContents(): Int { return 0 } companion object CREATOR : Parcelable.Creator<Person> { override fun createFromParcel(parcel: Parcel): Person { return Person(parcel) } override fun newArray(size: Int): Array<Person?> { return arrayOfNulls(size) } } }

Como puede ver, la implementación Parcelable es un código generado automáticamente agregado a su definición de clase de data .

Notas:

  1. Intentar convertir un Java Parcelable directamente en Kotlin no producirá el mismo resultado con la versión actual del complemento de Kotlin ( 1.1.3 ).
  2. Tuve que quitar algunas llaves extra que introduce el generador de código Parcelable actual. Debe ser un error menor.

Espero que este consejo te funcione tan bien como a mí.



Kotlin 1.1.4 está fuera

El complemento de extensiones de Android ahora incluye un generador automático de implementación Parcelable. Declare las propiedades serializadas en un constructor primario y agregue una anotación @Parcelize, y los métodos writeToParcel () / createFromParcel () se crearán automáticamente:

@Parcelize class User(val firstName: String, val lastName: String) : Parcelable

Por lo tanto, debe habilitarlos agregando esto al build.gradle de su módulo:

apply plugin: ''org.jetbrains.kotlin.android.extensions'' android { androidExtensions { experimental = true } }


  • Use la anotación @Parcelize en la parte superior de su clase de Modelo / Datos
  • Use la última versión de Kotlin
  • Use la última versión de Kotlin Android Extensions en su módulo de aplicación

Ejemplo:

@Parcelize data class Item( var imageUrl: String, var title: String, var description: Category ) : Parcelable