Partager un arrayList d’objet entre activity via Parcelable

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.

9 réflexions au sujet de « Partager un arrayList d’objet entre activity via Parcelable »

  1. lahbabi ali

    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!

    Répondre
    1. François

      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.

      Répondre
  2. alex

    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

    Répondre
    1. Olivier Auteur de l’article

      Instancie ton objet au niveau de l’activité et non du fragment, tu peux ainsi facilement le partager entre les fragment.

      Répondre
  3. Romain

    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.

    Répondre
  4. JC

    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 !

    Répondre
    1. Olivier Auteur de l’article

      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.

      Répondre

Répondre à lahbabi ali Annuler la réponse.

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *