Apprendre à passer des objets complexes entre deux activités via des extras en programmation Android

Prérequis pour bien comprendre ce tutoriel :

Pour réagir à ce tutoriel, un espace de dialogue vous est proposé sur le forum. Commentez Donner une note à l'article (5)

Article lu   fois.

Les deux auteurs

Profil ProSite personnel

Site personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Introduction

Aujourd'hui nous allons voir comment passer des données complexes entre deux pages de ton application, donc entre deux activités.

J'avais déjà fait un article expliquant comment passer des types simples entre deux activités, comme un entier, un booléen, un double, une String, etc.

Là nous allons voir comment passer l'objet que tu souhaites !


Passe des types complexes entre tes activités


II. Mise en place de l'application

II-A. La base de l'application

J'ai rouvert l'application que nous avions créée pour passer deux extras simples (comme les entiers, les booléens, etc.) entre deux activités.

Si tu n'as pas cette application sous les yeux, ce n'est pas grave. Ce qui compte, si tu veux faire le code en même temps que moi, c'est que tu aies une application qui a au moins deux pages (activités) et que tu aies un intent qui lance la deuxième activité.

Si tu as ça, tu pourras faire le code en même temps que moi. Sinon je t'invite simplement à suivre ce que je vais faire. Comme ça, le jour où tu en auras besoin, tu sauras que ça existe et tu auras juste à repasser sur cet article pour pouvoir l'implémenter.

II-B. Création de l'objet que l'on passera en extra

Le type que nous allons passer de la première à la seconde activité sera le type User. Nous allons donc créer cette classe !

Tu crées une nouvelle classe que tu appelles User. Tu vas lui donner deux attributs de type String : prenom et pseudo. Tu vas maintenant ajouter les getters pour ces deux attributs ainsi que le constructeur prenant en argument ces deux attributs. Pense à utiliser le raccourci « Alt+Insert » pour créer le constructeur ainsi que les getters automatiquement. Ce qui donne :

 
Sélectionnez
public class User {

    private String prenom;
    private String pseudo;

    public User(String prenom, String pseudo) {
        this.prenom = prenom;
        this.pseudo = pseudo;
    }
   
    public String getPrenom() {
        return prenom;
    }

    public String getPseudo() {
        return pseudo;
    }
}

La classe User est maintenant prête. Tu vas pouvoir l'instancier dans ton code Java, juste avant de lancer ta seconde activité. Ce qui donne pour moi :

User = new User("Sebastien", "Seb");

Ce que nous allons maintenant vouloir, c'est passer le user que nous venons de créer en extra à la seconde activité. Comment allons-nous faire ça ? Parce que là, si tu utilises la méthode putExtra, ça ne va pas fonctionner. La méthode putExtra ne connaitra pas le type User et ne pourra pas l'utiliser. Pour résoudre ce problème, notre classe User va devoir implémenter l'interface « Parcelable »

III. Implémenter l'interface « Parcelable »

III-A. Rendre la conversion de notre User vers le type Parcel possible

La classe User doit implémenter l'interface « Parcelable ». Pour implémenter une interface, tu utilises le mot clé « implements » suivi du nom de l'interface. Ce qui te donne :

 
Sélectionnez
public class User implements Parcelable {}

Android Studio te souligne maintenant toute la ligne ci-dessus en rouge, parce que tu n'as pas encore implémenté les méthodes de l'interface Parcelable. Pour corriger ça, tu fais « Alt+Entrée » sur la ligne soulignée en rouge, et tu cliques sur « Implement methods ». Tu sélectionnes bien toutes les méthodes que Android Studio te propose d'implémenter (il y en a deux).

F:\Vidéos\Formations Android\01 - Articles\developpez.net\2 - Parcelable\implement methods.png

Android Studio t'a créé les méthodes describeContents et writeToParcel.

Nous n'allons pas toucher à la méthode describeContents. Nous allons simplement laisser le return 0;. Si tu avais un objet spécial dans ta classe User comme un file descriptor, tu aurais dû renvoyer un autre flag, donc autre chose que 0. Je te reparlerai de ce flag juste après.

Nous ce qui nous intéresse c'est d'implémenter la méthode writeToParcel. Nous allons voir comment ajouter à notre Parcel les deux attributs de notre classe, à savoir « prenom » et « pseudo ». Pour ça, tu vas devoir appeler la méthode « writeString » sur l'argument parcel, pour enregistrer les attributs de la classe :

 
Sélectionnez
@Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeString(prenom);
        parcel.writeString(pseudo);
    }

Là tu as écrit dans la Parcel les informations importantes de ta classe. Les informations vont transiter via la Parcel, et ensuite nous recréerons notre instance de User depuis la Parcel. En fait, ce qui va passer entre les deux activités ce n'est pas directement ton instance de User, mais c'est l'objet de type Parcel (et qui contient les informations de ton instance de User).

La méthode prend un deuxième entier en argument (ici « i »), c'est un flag. Je vais t'expliquer ce que c'est. Pour ça, il y a la doc Android (voir la page parlant de Parcelable).

F:\Vidéos\Formations Android\01 - Articles\developpez.net\2 - Parcelable\docandroid.png

Pour revenir à la méthode « describeContents() », je t'avais dit que si, par exemple, tu avais un file descriptor, tu aurais dû retourner un flag différent de 0. C'est écrit dans la doc Android, comme tu peux le voir sur l'image ci-dessus. Tu aurais dû retourner le flag CONTENTS_FILE_DESCRIPTOR.

Concernant le flag de la méthode « writeToParcel », dans notre cas, il vaut 0, mais il peut prendre la valeur : PARCELABLE_WRITE_RETURN_VALUE. Nous ne le testons pas parce qu'on veut simplement passer notre User entre deux activités, mais dans certains cas, ça peut valoir le coup de tester ce flag. Pour information, ce flag vaut PARCELABLE_WRITE_RETURN_VALUE quand ta Parcel est le retour d'une méthode comme c'est expliqué dans la doc Android.

Là on a fait l'important au niveau du « putExtra », pour envoyer des informations d'une activité à une autre. On a réussi à transformer notre User en Parcel.

Maintenant ce qu'on veut, c'est qu'une fois qu'on aura notre Parcel dans la seconde activité, c'est de pouvoir la transformer en User.

III-B. Rendre la conversion du type Parcel vers le type User possible

Nous allons maintenant permettre à notre Parcel de se convertir en User. Tu constates que le nom de la classe « User » est encore souligné en rouge dans Android Studio. C'est parce que la classe User implémente l'interface Parcelable, mais que la classe User ne fournit pas le champ « CREATOR ».

Pour résoudre ce problème, tu vas faire « Alt+Entrée » sur « User » qui est souligné en rouge et tu vas sélectionner « Add Parcelable Implementation ».

F:\Vidéos\Formations Android\01 - Articles\developpez.net\2 - Parcelable\addCreator.png

Android Studio t'a maintenant ajouté les lignes suivantes :

 
Sélectionnez
protected User(Parcel in) {
        prenom = in.readString();
        pseudo = in.readString();
    }

    public static final Creator<User> CREATOR = new Creator<User>() {
        @Override
        public User createFromParcel(Parcel in) {
            return new User(in);
        }

        @Override
        public User[] newArray(int size) {
            return new User[size];
        }
    };

Qu'est-ce que c'est que tout ce code ? Comment ça fonctionne ?

Android Studio t'a ajouté le champ « Creator », qui est obligatoire quand tu implémentes Parcelable. À l'intérieur de ce champ, il t'a créé deux méthodes :

  • newArray : méthode qui permet d'avoir un tableau de « User ». La méthode est obligatoire, mais elle ne nous intéresse pas. Android Studio l'a déjà bien implémentée, et ça nous suffit amplement !
  • createFromParcel : cette méthode nous intéresse ! Elle permet de créer un User depuis une Parcel. C'est parfait, c'est ce que nous voulions faire ! Tu vois que la méthode va retourner un User. Pour créer le User, le constructeur User est appelé, en lui passant en argument une Parcel.

Jusqu'à maintenant, nous avions simplement un constructeur qui prenait en argument un prénom et un pseudo. Nous n'avions pas de constructeur qui prenait comme argument une Parcel. Mais Android Studio te l'a créé.

Android Studio t'a créé un nouveau constructeur qui prend en argument une Parcel, parfait ! Et en plus, Android Studio te l'a déjà implémenté, ce n'est pas magnifique ?

Mais il faut faire très attention à un point ! Quand tu crées le User à partir d'une Parcel, d'abord tu récupères l'attribut « prenom » puis l'attribut « pseudo ». L'ordre est très important dans ce cas-là ! L'ordre doit être le même que lorsque tu as fait l'écriture dans la Parcel, dans la méthode « writeToParcel ». Tu dois donc faire très attention que ce soit dans le même ordre si tu ne veux pas que tes champs soient mélangés.

 
Sélectionnez
protected User(Parcel in) {
        prenom = in.readString(); // d'abord le prenom
        pseudo = in.readString(); // ensuite le pseudo
    }

@Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeString(prenom); // d'abord le prenom
        parcel.writeString(pseudo); // ensuite le pseudo
    }

C'est bon ! Nous avons fait tout ce qu'il fallait dans la classe User !

IV. Faire transiter un User entre deux activités

Tu retournes sur ta MainActivity où tu as normalement déjà instancié un User. Tu n'as plus qu'à passer le User en utilisant la méthode « putExtra » sur l'intent, comme tu l'as déjà fait pour des entiers ou des Strings :

 
Sélectionnez
Intent intent = new Intent(this, MaDeuxiemeActivity.class);

User user = new User("Sebastien", "Seb");
intent.putExtra("user", user); // la clé, la valeur

startActivity(intent);

Tu peux maintenant aller dans ta deuxième activité pour récupérer le user.

Pour le récupérer, c'est très simple. Tu vas appeler la méthode getParcelableExtra sur l'intent (récupéré via la méthode getIntent()). Tu as juste à passer en argument à cette méthode la clé que tu souhaites. Ce qui donne :

 
Sélectionnez
Intent intent = getIntent();
if (intent != null){
    User user = intent.getParcelableExtra("user");
           if (user != null){
        // tu peux manipuler user !
    }
}

Tu peux maintenant récupérer les informations de ton user via les getters, et les afficher par exemple dans une TextView !

V. Quelques outils pour te faciliter la vie

Implémenter l'interface Parcelable pour une classe ou deux, ça va. Mais si tu dois en faire plus, ça peut vite devenir pénible. Tu as des outils qui te permettent de t'aider si c'est ton cas :

Je te laisse regarder ces deux outils si tu en as besoin, ils peuvent te faire gagner un temps précieux.

J'espère que ce tutoriel t'a plu, nous avons surtout vu comment implémenter l'interface Parcelable. Je te souhaite une bonne journée et je te dis à la prochaine !

VI. Note de la rédaction de Developpez.com

Nous tenons à remercier Claude Leloup pour la relecture orthographique de ce tutoriel.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Copyright © 2017 BeeApps - Sébastien DEPARDIEU. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.