Existe-t-il un moyen pratique de créer des classes de données Parcelables dans Android avec Kotlin?

J'utilise actuellement l'excellent AutoParcel dans mon projet Java, ce qui facilite la création de classes Parcelables.

Maintenant, Kotlin, que je considère pour mon prochain projet, a ce concept de classes de données, qui génèrent automatiquement les méthodes equals, hashCode et toString.

Existe-t-il un moyen pratique de rendre une classe de données Kotlin Parcelable de manière pratique (sans implémenter les méthodes manuellement)?

76
demandé sur thalesmello 2015-11-05 21:19:30

12 réponses

Kotlin 1.1.4 est

Le plugin Android Extensions inclut désormais un générateur automatique D'implémentation Parcelable. Déclarez les propriétés sérialisées dans un constructeur principal et ajoutez une annotation @ Parcelize, et les méthodes writeToParcel()/createFromParcel() seront créées automatiquement:

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

Vous devez donc les activer en ajoutant ceci à la construction de votre module.gradle :

apply plugin: 'org.jetbrains.kotlin.android.extensions'

android {
    androidExtensions {
        experimental = true
    }
}
102
répondu Dhaval Jivani 2018-08-19 04:06:05

, Vous pouvez essayer ce plugin:

Android-parcelable-ide-plugin-kotlin

Il vous aide à générer du Code Standard Parcelable Android pour la classe de données de kotlin. Et ça ressemble enfin à ceci:

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)
            }
        }
    }
}
42
répondu nekocode 2015-12-30 14:08:45

Avez-vous essayé PaperParcel? C'est un processeur d'annotation qui génère automatiquement le code standard Android Parcelable pour vous.

Utilisation:

Annotez votre classe de données avec @PaperParcel, implémentez PaperParcelable et ajoutez une instance statique JVM du CREATOR généré par exemple:

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

Maintenant votre classe de données est Parcelable et peut être transmis directement à un Bundle ou Intent

Edit: Mise à jour avec la dernière API

19
répondu Bradley Campbell 2016-11-27 08:33:41

Le meilleurs façon avec non réutilisable le code est Contrebandier plugin gradle. Tout ce dont vous avez besoin est simplement d'implémenter L'interface AutoParcelable comme

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

Et c'est tout. Fonctionne aussi pour les classes scellées. Ce plugin fournit également la validation de la compilation pour toutes les classes AutoParcelable.

UPD 17.08.2017 Maintenant avec Kotlin 1.1.4 et Kotlin extensions Android plugin vous pouvez utiliser @Parcelize annotation. Dans ce cas, l'exemple ci-dessus ressemblera à:

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

Pas besoin de data modificateur. Le plus grand inconvénient, pour l'instant, est d'utiliser le plugin Kotlin-Android-extensions qui a beaucoup d'autres fonctions qui pourraient être inutiles.

14
répondu Stepango 2017-08-17 08:59:44

Il suffit de cliquer sur le mot-clé data de votre classe de données kotlin, puis appuyez sur alt + Entrée, sélectionnez la première option en disant "Add Parceable Implementation"

7
répondu M_P 2018-03-22 10:17:24

Je vais laisser ma façon de faire au cas où cela pourrait aider quelqu'un.

Ce que je fais c'est que j'ai un générique Parcelable

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

Et puis je crée des parcelables comme ceci:

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()) } }
}

Ce Qui me débarrasse de ce remplacement standard.

4
répondu gmemario 2016-02-29 12:55:57

Malheureusement, il n'y a aucun moyen dans Kotlin de mettre un vrai champ dans une interface, donc vous ne pouvez pas l'hériter d'un adaptateur d'interface gratuitement: data class Par : MyParcelable

Vous pouvez regarder la délégation, mais cela n'aide pas avec les champs, AFAIK: https://kotlinlang.org/docs/reference/delegation.html

Donc, la seule option que je vois est une fonction de tissu pour Parcelable.Creator, ce qui est assez évident.

3
répondu voddan 2015-11-05 20:34:14

Je préfère simplement utiliser le https://github.com/johncarl81/parceler lib avec

@Parcel(Parcel.Serialization.BEAN)
data class MyClass(val value)
2
répondu Jan Rabe 2017-02-10 09:16:39

En Utilisant Android Studio et le pluginKotlin , j'ai trouvé un moyen facile de convertir mes anciens Java Parcelables avec Pas de plugins supplémentaires (Si tout ce que vous voulez est de transformer une toute nouvelle classe data en Parcelable, passez à l'extrait de code 4ème).

Disons que vous avez une classe Person avec toute la plaque de chaudière 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;
    }
}

Commencez par supprimer l'implémentation Parcelable, en laissant un objet Java simple et ancien (les propriétés doivent être finales et défini par le constructeur):

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

Alors laissez l'option Code > Convert Java file to Kotlin File Faire sa magie:

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

Convertissez ceci en une classe data:

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

Et enfin, transformons cela en un Parcelable à nouveau. Passez le nom de la classe et Android Studio devrait vous donner l'option Add Parcelable Implementation. Le résultat devrait ressembler à ceci:

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

Comme vous pouvez le voir, l'implémentation Parcelable est un code généré automatiquement ajouté à votre définition de classe data.

Notes:

  1. Essayer de convertir un Java Parcelable directement dans Kotlin ne produira pas le même résultat avec la version actuelle de la Kotlin plugin (1.1.3).
  2. j'ai dû enlever quelques accolades supplémentaires que le générateur de code actuel Parcelable introduit. Doit être un bug mineur.

J'espère que cette astuce fonctionne pour vous aussi bien que pour moi.

2
répondu argenkiwi 2017-06-24 00:52:57

Il y a un Plugin mais n'est pas toujours aussi mis à jour que Kotlin évolue: https://plugins.jetbrains.com/plugin/8086

Alternative: J'ai un exemple de travail d'une classe de données personnalisée en utilisant Parcelable et des listes:

Classes de données utilisant Parcelable avec des listes:

Https://gist.github.com/juanchosaravia/0b61204551d4ec815bbf

J'espère que ça aide!

0
répondu Juancho 2016-01-22 00:35:43

Kotlin a rendu l'ensemble du processus de Parcélisation dans Android sacrément facile avec son annotation @Parcel.

Pour ce faire

Étape 1. Ajoutez des extensions Kotlin dans votre module d'application gradle

Étape 2. Ajouter experimental = true puisque cette fonctionnalité est encore en expérimentation dans gradle.

AndroidExtensions { expérimental = vrai }

Étape 3. annoncer la classe de données avec @ Parcel

Ici est un exemple simple sur l'utilisation de @Parcel

0
répondu Ramakrishna Joshi 2018-07-22 09:04:50

Kotlin a rendu l'ensemble du processus de Parcélisation dans Android sacrément facile avec son annotation @Parcel.

Pour ce faire

Étape 1. Ajoutez des extensions Kotlin dans votre module d'application gradle

Étape 2. Ajouter experimental = true puisque cette fonctionnalité est encore en expérimentation dans gradle.

AndroidExtensions { expérimental = vrai }

Étape 3. annoncer la classe de données avec @ Parcel

Ici est un exemple simple sur l'utilisation de @Parcel dans Kotlin pour transmettre des données entre les composants Android.

0
répondu Ramakrishna Joshi 2018-07-22 18:53:23