Imaginons le cas classique d’une activité A , d’une activité B et d’un objet Personne. Comment transférer un arrayList de Personne entre A et B ?
Il faut simplement implémenter Parcelable pour l’objet personne et créer un liste d’objet elle même Parcelable.
Commençons par notre objet Personne très simple :
Class Personne { private String nom; private String prenom; public Personne(){} public Personne(String nom,String prenom) { this.nom = nom; this.prenom = prenom; } public void setNom(String nom){ this.nom = nom;} public void setPrenom(String prenom){ this.nom = prenom;} public String getNom(){return this.nom;} public String setNom(){return this.prenom} }
Rendre l’objet Parcelable
Implémentons l’interface Parcelable :
Class Personne implements Parcelable { //Même chose que précédent [...] //Second constructeur qui sera appelé lors de la "Deparcelablisation" public Personne(Parcel in) { this.getFromParcel(in); } @SuppressWarnings("rawtypes") public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { public Personne createFromParcel(Parcel in) { return new Personne(in); } @Override public Object[] newArray(int size) { return null; } }; @Override public int describeContents() { return 0; } //On ecrit dans le parcel les données de notre objet @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(this.nom); dest.writeString(this.prenom); } //On va ici hydrater notre objet à partir du Parcel public void getFromParcel(Parcel in) { this.setNom(in.readString()); this.setPrenom(in.readString()); } }
Les deux méthodes importantes sont writeToParcel et getFromParcel qui permettent respectivement d’écrire dans le Parcel et de lire dedans. Pour simplifier on « sérialise » l’objet avec writeToParcel et on le « déserialise » avec getFromParcel.
Notez que getFromParcel peut se nommer comme bon vous semble.
L’ordre des variables dans writeToParcel est important puisque vous devrez utiliser le même dans getFromParcel.
Vous avez à cet instant un objet Parcelable , ce qui veux dire que vous pouvez le passer d’une activité à une autre au travers d’un Bundle. Notre but étant de passer une liste il nous reste encore un peu de travail.
Créer un arrayList Parcelable
Pour pouvoir transférer une liste d’objet on va créer une liste de personne qui dérive de ArrayList et qui implémente parcelable. On reprend exactement le même principe que pour notre objet :
class PersonneList extends ArrayList<Personne> implements Parcelable { public PersonneList() { } public PersonneList(Parcel in) { this.getFromParcel(in); } @SuppressWarnings("rawtypes") public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { public PersonneList createFromParcel(Parcel in) { return new PersonneList(in); } @Override public Object[] newArray(int size) { return null; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { //Taille de la liste int size = this.size(); dest.writeInt(size); for(int i=0; i < size; i++) { Personne pers = this.get(i); //On vient lire chaque objet personne dest.writeString(pers.nom); dest.writeString(pers.prenom); } } public void getFromParcel(Parcel in) { // On vide la liste avant tout remplissage this.clear(); //Récupération du nombre d'objet int size = in.readInt(); //On repeuple la liste avec de nouveau objet for(int i = 0; i < size; i++) { Personne pers = new Personne(); pers.setNom(in.readString()); pers.setPrenom(in.readString()); this.add(pers); } } }
Nous avons donc désormais un objet parcelable ainsi qu’une liste. Il ne nous reste plus qu’à peupler la liste d’objet et de transmettre la liste entre les activités :
Intent myIntent = new Intent(Activity_A.this,Activity_B.class); myIntent.putExtra("identifiantListe",(Parcelable)monObjet_personneList); startActivity(myIntent);
Pour récupérer la liste d’objet dans l’autre activité il suffit de récupérer le bundle :
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(); Bundle b = getIntent().getExtras(); PersonneList maliste = b.getParcelable("identifiantListe"); }
Et si mon objet contient d’autres objets ?
Il n’est pas rare d’avoir un objet qui en contient d’autre. Dans ce cas comment faire puisque Parcel n’a que des méthode de lecture et d’écriture de type primitifs ?
Et bien tout d’abord il faut que cet objet inclus soit lui aussi Parcelable. Puis dans les deux méthodes writeToParcel et getFromParcel il vous suffit d’écrire/lire cet objet via writeParcelable et readParcelable.
Exemple :
//On ecrit dans le parcel les données de notre objet @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(this.nom); dest.writeString(this.prenom); dest.writeParcelable(this.listeAnimaux,flags); // On écrit la liste des animaux de la personne } //On va ici hydrater notre objet à partir du Parcel public void getFromParcel(Parcel in) { this.setNom(in.readString()); this.setPrenom(in.readString()); // On lit la liste des animaux de la personne this.listeAnimaux = in.readParcelable(ListeAnimaux.class.getClassLoader()); }
Vous devriez normalement avec cette méthode faire transitez tous les objets ou liste d’objets que vous souhaitez entre deux activités.
j’ai utilisé votre méthode mais quand j’exécute je retrouve des erreurs de nulPointerException ici »
Bundle b = getIntent().getExtras();
listerv = b.getParcelable(« list »); »//listerv est null
mon objet listerv est un arraylist de RendezVous que je veux récupere dans la seconde acitivite,j’ai implémenté Parcelable sur RendezVous et GestionRendezVous comme vous l’avez fait en plus de toutes les méthodes que vous avez utilisé mais hélas pas de résultats, svp si vous pouvez m’aider il existe pas bcp de référence sur internet je vous serrai d’une grande gratitude Merci bcp!
Bonjour,
Je dois actuellement faire passer une liste d’objet d’une activité à une autre.
Cette liste d’objet je la crée grâce au résultat d’un json sur un fichier php qui va interroger ma base de donnée, cette liste d’objet je la retourne a mon application grâce à un callback.
Par contre lorsque j’ai essayer de la mettre dans un intent pour la passer à l’activité suivant, je me suis retrouvé dans une impasse et je suis donc tombé sur votre tuto.
J’ai suivit votre tutoriel, et j’ai donc modifier ma classe d’objet et créé une class de liste d’objet afin de pouvoir les parceller, mais lorsque j’essaie de mettre ma liste d’objet dans mon intent je me retrouver avec le intet souligné en rouge et l’erreur suivante qui apparait:
Non-static method ‘putEtra(java.lang.String, android.os.Parcelable)’ cannot be referenced from a static context
Sauriez-vous me dire ce que je dois faire?
Je précise que je fais plus que débuter sur android.
Salut,
merci pour ce tuto, cependant mon probleme a moi est que j’utilise les fragments et je ne sais pas comment faire pour récupérer mon objet parcelable instancié dans un premier fragment dans un deuxieme ?
Peut tu m’éclairer ?
Merci
Instancie ton objet au niveau de l’activité et non du fragment, tu peux ainsi facilement le partager entre les fragment.
Ok je testerai ça merci !
Bonjour, j’ai utilisé votre méthode (pas avec des personnes mais je vais me mettre dans votre contexte).
Mon problème est que dans ma deuxième activité, au lieu de récupérer une liste de personne, il ne récupère qu’une personne (qui est vide qui plus est).
Grâce à des messages consoles, j’ai remarqué qu’il n’appelait jamais le getFromParcel de la liste de personne.
J’ai cherché autres parts mais je ne trouve pas de solution à mon problème, si vous en avez une je suis preneur. Si vous avez besoin du code, je ne reste disponible.
Cordialement.
Au moment où j’ai posté le message, j’ai résolu mon problème, désolé du dérangement et merci pour l’aide du tuto!
Merci pour ce Tuto. Existe-t-il, comme en C++, un moyen de transmettre un pointeur d’une liste d’objet vers une seconde activité, qui fait que l’on peut modifier ou ajouter des objets de cette liste qui affecterons forcement la même liste d’objet présente dans l’activité principale ?
Merci !
Quand tu passes un objet il est forcément passé par référence en java. Sauf que dans ce cas précis on fait de la sérialisation et quand tu passes d’une activité A à une activité B , l’activité A est « tuée ».
Si ton activité B doit retourner des données à l’activité A , tu devrais peut plutôt utiliser startActivityForResult() qui justement permet ce fonctionnement.
bonjour j’ai utlisé cette méthode mais ça ne parvient toujours pas à récuperer les objets