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.
Hay un complemento, pero no siempre está tan actualizado como Kotlin está evolucionando: android-parcelable-intellij-plugin-kotlin
Alternativa:
tengo un ejemplo funcional de una clase de datos personalizada que utiliza
Parcelable
y listas:
Clases de datos que usan Parcelable con listas:
¡Espero eso ayude!
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:
-
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
). -
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í.
prefiero simplemente usar la https://github.com/johncarl81/parceler lib con
@Parcel(Parcel.Serialization.BEAN)
data class MyClass(val value)
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