[JAVA] J'ai essayé de générer automatiquement une classe à convertir d'une classe de données en un bundle avec APT

Contexte

C'est difficile de définir des données dans Bundle ... Surtout la définition de la chaîne de clé est super gênante ... Pour être honnête, Serialize et Parcelable sont ennuyeux ...

Plus précisément, ça ressemble à ça ↓ ↓ ↓ travail ... C'est ennuyeux ...

Travailler pour emballer les valeurs dans Bundle


final Bundle args = new Bundle();
args.putInt("key_id", value.getId());
args.putString("key_tag", value.getTag());
args.putBoolean("key_enabled", value.isEnabled());

Fragment de valeurs de Bundle


final Bundle args = getArguments();
final int id = args.getInt("key_id");
final String tag = args.getString("key_tag");
final boolean isEnabled = args.getBoolean("key_enabled");

Chose que tu veux faire

Je veux créer automatiquement une classe qui peut récupérer une valeur d'un Bundle qui la change en Bundle simplement en ajoutant une annotation comme AutoValue. Plus précisément, je souhaite utiliser l '«Outil de traitement des annotations» pour générer automatiquement une classe qui répond aux exigences suivantes.

Image de mise en œuvre

Une classe automatique est générée lorsque vous créez en annotant la valeur que vous souhaitez enregistrer dans la classe de données

Échantillon (classe de modèle)


@BundleGenerator //Spécifiez la classe
public class Sample {
 
    private final int mId;
 
    public Sample(int id) {
        mId = id;
    }
 
    @BundleSet //Spécifiez une valeur
    public int getId() { return mId; }
}

Les classes suivantes sont automatiquement générées par build.

SampleBundleGenerator (classe générée automatiquement)


//Nom de la classe de données+Généré automatiquement par BundleGenerator
public class SampleBundleGenerator {
    //Méthode de conversion du modèle en bundle
    @NonNull
    public static Bundle bundle(@NonNull Sample target) {
        return bundle(target, new Bundle());
    }
  
    @NonNull
    public static Bundle bundle(@NonNull Sample target, @NonNull Bundle bundle) {
        bundle.putInt("xxx.xxx.Sample_getId", target.getId());
        return bundle;
    }
 
    //Méthode pour récupérer la valeur de Bundle
    @NonNull
    public static Wrapper restore(@NonNull Bundle bundle) {
        return new Wrapper(bundle);
    }
 
    public static class Wrapper {
        final Bundle mBundle;
 
        BundleWrapper(@NonNull Bundle bundle) {
            mBundle = bundle;
        }
 
        public int getId() {
            return mBundle.getInt("xxx.xxx.Sample_getId");
        }
    }
}

Si vous transmettez la classe de données à la classe générée automatiquement, elle sera convertie en Bundle.

Définir les données dans Bundle


Bundle bundle = SampleBundleGenerator.bundle(value);

Si vous transmettez à nouveau le Bundle converti à la classe générée automatiquement, vous pouvez obtenir la valeur de la classe de modèle d'origine.

Récupérer les valeurs du bundle


SampleBundleGenerator.Wrapper sample = SampleBundleGenerator.restore(getArguments());

Livrables

Cliquez ici pour le résultat de sa mise en œuvre pour le moment → github: BundleGenerator

Méthode de mise en œuvre APT

Les détails sont publiés dans d'autres articles, de sorte que seul le flux général est présenté.

(1) Créer un nouveau projet avec Android Studio (comme créer une application normalement)

(2) Ajout de "java library" dans un nouveau module (il est facile de comprendre si le nom du module est processor)

(3) Créez une classe qui hérite de AbstractProcessor côté bibliothèque et une classe d'annotations que vous souhaitez utiliser (dans la classe Processor, trouvez l'élément qui a été annoté au moment de la compilation et générez automatiquement la classe que vous souhaitez réaliser)

@SupportedAnnotationTypes({
    "abj.bundlegenerator.processor.BundleGenerator",
    "abj.bundlegenerator.processor.BundleSet"})
@SupportedSourceVersion(SourceVersion.RELEASE_7)
public class BundleGeneratorProcessor extends AbstractProcessor {
 
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        //Générez une classe ici
        //A partir de l'argument roundEnv, extrayez l'élément correspondant à l'annotation souhaitée et utilisez ces informations pour générer une classe.
        //Créer des classes est très facile avec une bibliothèque appelée JavaPoet
    }
}

(4) Définissez le point d'entrée du processeur afin que javac puisse être accroché. Créez un fichier appelé javax.annotation.processing.Processor ci-dessous et décrivez le nom de classe du processeur d'annotation créé (abj.bundlegenerator.processor.BundleGeneratorProcessor ci-dessus) metainf.png

(5) Définissez la bibliothèque du côté du module que vous souhaitez utiliser

build.gradle


dependencies {
    implementation project(':processor')
    annotationProcessor project(':processor')
}

référence

https://qiita.com/LyricalMaestro0/items/9a4e3ec3ea7bda9ee523 https://qiita.com/opengl-8080/items/beda51fe4f23750c33e9 https://qiita.com/shiraji/items/ed674c5883ed0520791b

Recommended Posts

J'ai essayé de générer automatiquement une classe à convertir d'une classe de données en un bundle avec APT
J'ai essayé de générer une source de programme en langage C à partir de cURL
J'ai essayé de casser le bloc avec java (1)
J'ai essayé de démarrer avec Spring Data JPA
J'ai créé un programme qui recherche la classe cible à partir du processus surchargé avec Java
J'ai essayé de créer un environnement de développement java8 avec Chocolatey
J'ai essayé de moderniser une application Java EE avec OpenShift.
[Rails] J'ai essayé de créer une mini application avec FullCalendar
J'ai essayé de convertir une chaîne de caractères en un type LocalDate en Java
J'ai essayé de créer un environnement de développement padrino avec Docker
J'ai essayé de créer une fonction de groupe (babillard) avec Rails
J'ai essayé d'exprimer les résultats avant et après de la classe Date avec une ligne droite numérique
J'ai essayé de créer une classe parent d'objet de valeur dans Ruby
[Pour les débutants] Je souhaite saisir automatiquement des données pré-enregistrées dans le formulaire de saisie avec une commande de sélection.
J'ai essayé de démarrer avec Web Assembly
[iOS] J'ai essayé de créer une application de traitement de type insta avec Swift
J'ai essayé de créer une API Web qui se connecte à DB avec Quarkus
J'ai essayé de jouer un peu avec BottomNavigationView ①
J'ai essayé de créer un portefeuille avec AWS, Docker, CircleCI, Laravel [avec lien de référence]
J'ai essayé d'implémenter une fonction équivalente à Felica Lite avec HCE-F d'Android
J'ai essayé de faire un jeu simple avec Javafx ① "Trouvons le jeu du bonheur" (inachevé)
[Java] J'ai essayé de me connecter en utilisant le pool de connexion avec Servlet (tomcat) & MySQL & Java
[Android] J'ai créé un écran de liste de matériaux avec ListView + Bottom Sheet
J'ai essayé de cloner une application Web pleine de bugs avec Spring Boot
J'ai essayé de convertir Java Bean et XML avec le formateur XML de Jackson à cette époque
Transformer d'une classe normale en un style lambda
J'ai essayé de faire une authentification de base avec Java
J'ai essayé de gérer la configuration des jambes de force avec Coggle
J'ai essayé de gérer les informations de connexion avec JMX
java j'ai essayé de casser un simple bloc
J'ai essayé de développer un site Web pour étudier DUO3.0.
Convertissez une chaîne en un tableau caractère par caractère avec Swift
J'ai essayé de frapper une méthode Java d'ABCL
Comment convertir un contrat de solidité en une classe de contrat Java
J'ai essayé de créer une application de clonage LINE
Je veux jouer avec Firestore de Rails
J'ai essayé de développer un site Web pour enregistrer les dépenses.
J'ai essayé d'implémenter un serveur en utilisant Netty
Comment générer automatiquement un constructeur dans Eclipse
J'ai essayé de créer une fonction / écran d'administrateur de site commercial avec Java et Spring
J'ai essayé de faire un jeu simple avec Javafx ① "Trouvons le jeu du bonheur" (version inachevée ②)
J'ai essayé d'appeler une vidéo YouTube de DB avec haml et de l'afficher intégrée
[Azure] J'ai essayé de créer une application Java gratuitement ~ Se connecter avec FTP ~ [Débutant]
Une histoire à laquelle j'étais accro lors de l'obtention d'une clé qui a été automatiquement essayée sur MyBatis
J'ai essayé ce que je voulais essayer avec Stream doucement.
J'ai essayé d'implémenter le téléchargement de fichiers avec Spring MVC
Je veux appeler une méthode d'une autre classe
J'ai essayé d'implémenter TCP / IP + BIO avec JAVA
J'ai essayé de développer un site Web de partage de boutique de ramen.
J'ai démarré MySQL 5.7 avec docker-compose et j'ai essayé de me connecter
J'ai essayé de créer une compétence Clova en Java
Je souhaite surveiller un fichier spécifique avec WatchService