Les Parcelables sous Android

Le but de cet article est d’introduire une notion assez particulière à l’univers Android, il s’agit des Parcelables.

Problématique

Passer des données entre des activités est très facile sous Android. Normalement on utilise les Bundles. Mais que se passe t-il quand on veut envoyer des objets complexes d’une activité à une autres ?

Le système basé sur les Parcels est utilisé nativement par Android, il transforme des objets en Parcel, ce qui permet de passer des informations entre les activités.
Pour être clair, on peux dire que c’est l’équivalent de la sérialisation pour le passage d’objet entre différentes activités ou différents processus (IPC – Inter-Process Communication).

Pour pouvoir passer un objet complexe en utilisant le Bundle, il suffit que la classe représentant votre objet implémente l’interface Parcelable

Exemple

Imaginons une classe User, cette classe se composera d’un :

  • Nom
  • Prénom
  • Pseudo
  • Adresse Mail
  • Twitter
  • Profil Google +

Pour commencer notre tutoriel nous allons créer un simple projet Android. 

Une fois cette étape effectuée, on va créer une classe User


public class User
{
  private String mFirstName;
  private String mLastName;
  private String mPseudo;
  private String mMail;
  private String mTwitter;
  private String mGooglePlus;

  public User(String firstName, String lastName, 
String pseudo, String mail, String twitter, 
String googlePlus)
  {
    super();
    this.mFirstName = firstName;
    this.mLastName = lastName;
    this.mPseudo = pseudo;
    this.mMail = mail;
    this.mTwitter = twitter;
    this.mGooglePlus = googlePlus;
  }
}

Maintenant pour pouvoir utiliser cette classe dans un Bundle, il faut faire en sorte que la classe implémente Parcelable.
Ce qui rajoute les deux méthodes suivantes :

  • describeContents : Sert à décrire le contenu de notre Parcel et plus précisément le nombre d’objet spéciaux contenus dans votre Parcel
  • writeToParcel : Sert à écrire l’objet dans un Parcel.

Ce qui donne :

@Override
public int describeContents()
{
	return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags)
{
	dest.writeString(mFirstName);
	dest.writeString(mLastName);
	dest.writeString(mPseudo);
	dest.writeString(mMail);
	dest.writeString(mTwitter);
	dest.writeString(mGooglePlus);
}

Vous remarquez que dans la méthode writeToParcel, on écrit juste les différents attributs de notre classe dans le Parcel passé en argument à notre méthode.

Une dernière étape est nécessaire, elle consiste en la création d’un objet CREATOR de la classe Parcelable ainsi qu’un constructeur prenant comme argument un Parcel pour notre User (Pour reconstruire l’objet à partir d’un Parcel). Ce dernier pourra construire une instance de User à partir d’un Parcel

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

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

public User(Parcel in) {
	this.mFirstName = in.readString();
	this.mLastName = in.readString();
	this.mPseudo = in.readString();
	this.mMail = in.readString();
	this.mTwitter = in.readString();
	this.mGooglePlus = in.readString();
}

Le CREATOR vous permet d’indiquer comment votre objet de type Parcelable sera créé.

Vous remarquez que l’ordre de lecture dans le constructeur est le même que dans la méthode writeToParcel

Pour tester notre exemple, nous allons créer dans notre première activité (celle créé par défaut à la création du projet) un bouton afin de basculer à la deuxième activité au moment du click.

Button connectBtn = (Button) findViewById(R.id.connect);
connectBtn.setOnClickListener(new OnClickListener()
{
  @Override
  public void onClick(View v)
  {
        User user = new User("Nazim", "Benbourahla", "n_benbourahla", "benbourahla.nazim@gmail.com", "@n_benbourahla", "Nazim Benbourahla");
        Intent intent = new Intent(ParcelableExampleActivity.this, ResultActivity.class);
        intent.putExtra("user", user);
        startActivity(intent);
  }
});

Vous remarquez, il suffit simplement de passer l’objet dans la méthode putExtra avec la clé correspondante. Aussi simple que ça.

Nous allons ensuite créer une deuxième activité qui se compose d’un unique TextView (Xml + Activité) sans oublier de la déclarer dans le manifest.
Voici la partie du code qui nous intéresse :

@Override
public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.result);
    
   User user = getIntent().getExtras().getParcelable("user");
   TextView displayUser = (TextView) findViewById(R.id.displayUser);
        displayUser.setText("User : " + "\n" + " FirstName : " + 
        user.getmFirstName() + "\n" + " LastName : " + user.getmLastName() + 
        "\n" + " Pseudo : " + user.getmPseudo() + "\n" + " Email : " + 
        user.getmMail() + "\n" + " Twitter : " + user.getmTwitter() + 
        "\n" + " Google + : " + user.getmGooglePlus());
}

On récupère tout simplement l’objet grâce à la méthode getParcelable, puis on reconstruit l’objet User.

Et voici le résultat :

Conclusion

Ce tutoriel se termine ici, en espérant qu’il vous a aidé à comprendre l’utilité d’un Parcelable et comment l’utiliser.
Vous pouvez trouvez ici le code source du projet.

14 commentaires



  1. Merci pour ce tuto génial 😀 ça m’a beaucoup aidé!

    Répondre

  2. Franchement, pas génial comme tuto, faire passer un ensemble de String je ne trouve pas ça sorcier.

    Quel est donc la solution lorsque l’on dispose de Socket, InputStream et OutputStream …

    Répondre

    1. Bonjour,
      Vous pouvez créer une classe qui contient tout vos objets, en implémentant l’interface Serializable.
      Ensuite il devient possible de la stocker dans un bundle en utilisant les méthodes :
      bundle.putSerializable(“nomDeLaClasse”, maClasseSerializable);
      et
      maClasseSerializable = bundle.getSerializable(“nomDeLaClasse”);

      Répondre

  3. Merci pour ce tuto mais dans ma situation, l’objet que je veux faire passer contient une arrayList d’autre objet…
    Que faire ?

    Répondre

    1. J’ai le même problème.
      Quand j’ai essayé un writeList() ça se passe bien, par contre lorsque j’utilise le readList(list_a_implémenter, classLoader), il m’affiche une erreur.

      Que faire ?

      Répondre

      1. Merci pour le tuto, par contre je suis dans le meme cas que FriFri et anthony…

        Répondre

Laisser un commentaire

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