El complemento kotlin-parcelize
proporciona un generador de implementaciones Parcelable
.
Para incluir compatibilidad con Parcelable
, agrega el complemento de Gradle al archivo build.gradle
de tu app:
Groovy
plugins { id 'kotlin-parcelize' }
Kotlin
plugins { id("kotlin-parcelize") }
Cuando anotas una clase con @Parcelize
, se genera automáticamente una implementación Parcelable
, como se muestra en el siguiente ejemplo:
import kotlinx.parcelize.Parcelize
@Parcelize
class User(val firstName: String, val lastName: String, val age: Int): Parcelable
@Parcelize
requiere que todas las propiedades serializadas se declaren en el constructor principal. El complemento emite una advertencia en cada propiedad con un campo de respaldo declarado en el cuerpo de la clase. Además, no puedes aplicar @Parcelize
si algunos de los parámetros del constructor principal no son propiedades.
Si tu clase requiere una lógica de serialización más avanzada, escríbela dentro de una clase complementaria:
@Parcelize
data class User(val firstName: String, val lastName: String, val age: Int) : Parcelable {
private companion object : Parceler<User> {
override fun User.write(parcel: Parcel, flags: Int) {
// Custom write implementation
}
override fun create(parcel: Parcel): User {
// Custom read implementation
}
}
}
Tipos admitidos
@Parcelize
admite una amplia variedad de tipos:
- Tipos primitivos (y sus versiones encuadrados)
- Objetos y enumeraciones
String
,CharSequence
Duration
Exception
Size
,SizeF
,Bundle
,IBinder
,IInterface
,FileDescriptor
SparseArray
,SparseIntArray
,SparseLongArray
,SparseBooleanArray
- Todas las implementaciones de
Serializable
(incluidasDate
) yParcelable
- Colecciones de todos los tipos compatibles:
List
(mapeado aArrayList
),Set
(mapeado aLinkedHashSet
),Map
(mapeado aLinkedHashMap
)- También hay una cantidad de implementaciones concretas:
ArrayList
,LinkedList
,SortedSet
,NavigableSet
,HashSet
,LinkedHashSet
,TreeSet
ySortedMap
,NavigableMap
,HashMap
,LinkedHashMap
,TreeMap
,ConcurrentHashMap
- También hay una cantidad de implementaciones concretas:
- Arreglos de todos los tipos compatibles
- Versiones anulables de todos los tipos compatibles
Parceler
personalizados
Si tu tipo no se admite directamente, puedes escribir un objeto de mapeo Parceler
.
class ExternalClass(val value: Int)
object ExternalClassParceler : Parceler<ExternalClass> {
override fun create(parcel: Parcel) = ExternalClass(parcel.readInt())
override fun ExternalClass.write(parcel: Parcel, flags: Int) {
parcel.writeInt(value)
}
}
Puedes aplicar paquetes externos mediante las anotaciones @TypeParceler
o @WriteWith
:
// Class-local parceler
@Parcelize
@TypeParceler<ExternalClass, ExternalClassParceler>()
class MyClass(val external: ExternalClass) : Parcelable
// Property-local parceler
@Parcelize
class MyClass(@TypeParceler<ExternalClass, ExternalClassParceler>() val external: ExternalClass) : Parcelable
// Type-local parceler
@Parcelize
class MyClass(val external: @WriteWith<ExternalClassParceler>() ExternalClass) : Parcelable
Omitir propiedades de la serialización
Si quieres omitir que se parcele una propiedad, usa la anotación @IgnoredOnParcel
. También se puede usar en propiedades dentro de
el cuerpo de la clase para silenciar las advertencias que indican que la propiedad no se serializa.
Las propiedades del constructor con anotaciones @IgnoredOnParcel
deben tener un valor predeterminado
valor.
@Parcelize
class MyClass(
val include: String,
// Don't serialize this property
@IgnoredOnParcel val ignore: String = "default"
): Parcelable {
// Silence a warning
@IgnoredOnParcel
val computed: String = include + ignore
}
Usa android.os.Parcel.writeValue para serializar una propiedad
Puedes anotar un tipo con @RawValue
para que se use Parcelize.
Parcel.writeValue
para esa propiedad.
@Parcelize
class MyClass(val external: @RawValue ExternalClass): Parcelable
Esto puede fallar en el tiempo de ejecución si el valor de la propiedad no es compatibles con Android de forma nativa.
Parcelize también puede requerir que uses esta anotación cuando no haya otra de serialización de la propiedad.
Parcela con interfaces y clases selladas
Parcelize requiere una clase para parcelize para que no sea abstracta. Esta limitación
no para las clases selladas. Cuando se usa la anotación @Parcelize
en un
sellada, no es necesario que se repita para las clases derivadas.
@Parcelize
sealed class SealedClass: Parcelable {
class A(val a: String): SealedClass()
class B(val b: Int): SealedClass()
}
@Parcelize
class MyClass(val a: SealedClass.A, val b: SealedClass.B, val c: SealedClass): Parcelable
Comentarios
Si tienes algún problema con el complemento kotlin-parcelize
de Gradle, informa un error.