Archives par étiquette : ArrayList

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.