Générateur d'implémentation Parcelable

Le plug-in kotlin-parcelize fournit un générateur d'implémentation Parcelable.

Pour inclure la compatibilité avec Parcelable, ajoutez le plug-in Gradle au fichier build.gradle de votre application :

Groovy

plugins {
    id 'kotlin-parcelize'
}

Kotlin

plugins {
    id("kotlin-parcelize")
}

Lorsque vous annotez une classe avec @Parcelize, une implémentation Parcelable est automatiquement générée, comme illustré dans l'exemple suivant :

import kotlinx.parcelize.Parcelize

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

@Parcelize nécessite que toutes les propriétés sérialisées soient déclarées dans le constructeur principal. Le plug-in émet un avertissement sur chaque propriété avec un champ de support déclaré dans le corps de la classe. De plus, vous ne pouvez pas appliquer @Parcelize si certains paramètres du constructeur principal ne sont pas des propriétés.

Si votre classe nécessite une logique de sérialisation plus avancée, écrivez-la dans une classe compagnon :

@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
        }
    }
}

Types acceptés

@Parcelize accepte un large éventail de types :

  • Types primitifs (et leurs versions encapsulées)
  • Objets et énumérations
  • String, CharSequence
  • Duration
  • Exception
  • Size, SizeF, Bundle, IBinder, IInterface, FileDescriptor
  • SparseArray, SparseIntArray, SparseLongArray, SparseBooleanArray
  • Toutes les implémentations Serializable (y compris Date) et Parcelable
  • Les collections de tous les types compatibles : List (mappé sur ArrayList), Set (mappé sur LinkedHashSet), Map (mappé sur LinkedHashMap)
    • Plusieurs implémentations concrètes sont également possibles : ArrayList, LinkedList, SortedSet, NavigableSet, HashSet, LinkedHashSet, TreeSet, SortedMap, NavigableMap, HashMap, LinkedHashMap, TreeMap, ConcurrentHashMap
  • Tableaux de tous les types compatibles
  • Versions nullable de tous les types compatibles

Parceler personnalisés

Si votre type n'est pas directement pris en charge, vous pouvez écrire un objet de mappage 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)
    }
}

Vous pouvez appliquer des Parceler externes à l'aide d'annotations @TypeParceler ou @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

Ignorer les propriétés de la sérialisation

Si vous ne souhaitez pas que certains biens soient morcelés, utilisez la méthode Annotation @IgnoredOnParcel. Il peut également être utilisé sur les propriétés d'une corps de la classe pour mettre sous silence les avertissements indiquant que la propriété n'est pas sérialisée. Les propriétés de constructeur annotées avec @IgnoredOnParcel doivent avoir une valeur par défaut .

@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
}

Utiliser android.os.Parcel.writeValue pour sérialiser une propriété

Vous pouvez annoter un type avec @RawValue pour que Parcelize l'utilise. Parcel.writeValue pour cette propriété.

@Parcelize
class MyClass(val external: @RawValue ExternalClass): Parcelable

Cette opération peut échouer au moment de l'exécution si la valeur de la propriété n'est pas compatible de manière native avec Android.

La fonctionnalité Parcelize peut également vous obliger à utiliser cette annotation lorsqu'il n'existe aucune autre moyen de sérialiser la propriété.

Parcéliser à l'aide de classes scellées et d'interfaces scellées

Avec Parcelize, une classe de segmentation ne doit pas être abstraite. Cette limite ne fait ne sont pas conservées pour les classes scellées. Lorsque l'annotation @Parcelize est utilisée sur une scellée, il n'est pas nécessaire de la répéter pour les classes dérivées.

@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

Commentaires

Si vous rencontrez des problèmes avec le plug-in Gradle kotlin-parcelize, vous veuillez signaler un bug.