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 :
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 :
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).
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 :
@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).
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 ».
Android Studio t'a maintenant ajouté les lignes suivantes :
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.
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 :
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 :
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 :
- http://www.parcelabler.com : un site où tu copies/colles ta classe et il va implémenter l'interface Parcelable pour toi ;
- https://github.com/mcharmas/android-parcelable-intellij-plugin : un plugin pour Android Studio.
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.