web-dev-qa-db-fra.com

Utilisation de Parceler avec la classe de données Kotlin avec constructeur pour la sérialisation

Existe-t-il un moyen d'utiliser Parceler avec les classes de données Kotlin et le constructeur pour la sérialisation sans utiliser d'annotation @ParcelProperty pour chaque champ?

Si j'essaie d'utiliser une bibliothèque comme celle-ci:

@Parcel
data class Valve @ParcelConstructor constructor(val size: Int)

Je reçois Error:Parceler: No corresponding property found for constructor parameter arg0. Mais si j'ajoute @ParcelProperty("size") cela fonctionne très bien.
Pourquoi donc?

Mise à jour :
Il existe une autre façon d'utiliser cette bibliothèque.
Je pourrais simplement supprimer l'annotation @ParcelConstructor, mais j'obtiendrai une erreur
Error:Parceler: No @ParcelConstructor annotated constructor and no default empty bean constructor found.
Je pense (je ne l'ai pas testé) que je pourrais également rendre tous les paramètres du constructeur facultatifs et ajouter @JvmOverloads mais cela a un effet secondaire que je dois vérifier toutes les propriétés de la classe si elles sont nulles ou non.

Mise à jour 2 :
C'est ce qui a fonctionné pour moi:

@Parcel
data class Valve(val size: Int? = null)

En bref Java doit avoir un constructeur vide par défaut. Une façon d'y parvenir est de faire comme ci-dessus - toutes les variables doivent avoir des valeurs par défaut.

23
Martynas Jurkus

Selon les documents, Parceler fonctionne par défaut avec les champs publics. Mais un Kotlin habituel data class (comme dans votre exemple) est plutôt un "bean getter/setter traditionnel", car chaque propriété Kotlin est représentée par un champ privé et un getter/[setter].

TL; DR: Je pense que cela fonctionnera:

@Parcel(Serialization.BEAN)
data class Valve(val size: Int = 10)

Notez la valeur par défaut, elle permet à Kotlin de générer automatiquement un constructeur vide supplémentaire, qui est requis par la spécification Java Been).

Une autre façon serait de marquer le constructeur que nous avons déjà:

@Parcel(Serialization.BEAN)
data class Driver @ParcelConstructor constructor(val name: String)

Le document spécifique: https://github.com/johncarl81/parceler#gettersetter-serialization

28
voddan

Je sais que cette question a déjà une réponse, mais pour les futurs téléspectateurs qui ont également du mal à faire fonctionner Parceler avec des objets de données kotlin, j'ai écrit un nouveau processeur d'annotation pour générer le passe-partout Parcelable pour les classes de données Kotlin. Il est conçu pour réduire massivement le code passe-partout en rendant vos classes de données parcellables:

https://github.com/grandstaish/paperparcel

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 transmise directement à un Bundle ou Intent

Modifier: Mise à jour avec la dernière API

10
Bradley Campbell

Ajoutez simplement le constructeur par défaut:

@Parcel
data class Valve(val size: Int) {
    constructor() : this(0)
}
5
dmitriyzaitsev

si vous utilisez Kotlin 1.1.4 ou supérieur, il est plus facile d'utiliser l'annotation @Parcelize

Pour ce faire, ajoutez d'abord ceci à build.gradle

Android {
    //other codes

    //for using latest experimental build of Android Extensions
    androidExtensions {
        experimental = true
    }
}

Ensuite, changez votre classe comme ça

@Parcelize
data class Valve(val size: Int? = null) : Parcelable
2
Radesh