Android
Parcelable
Recherche…
Introduction
Parcelable est une interface spécifique à Android où vous implémentez vous-même la sérialisation. Il a été créé pour être beaucoup plus efficace que Serializable, et pour contourner certains problèmes avec le schéma de sérialisation Java par défaut.
Remarques
Il est important de garder à l'esprit que l'ordre dans lequel vous écrivez des champs dans une parcelle DOIT ÊTRE LE MÊME ORDRE que vous les lisez dans la parcelle lors de la construction de votre objet personnalisé.
L'interface parcellaire a une limite de taille stricte de 1 Mo. Cela signifie que tout objet ou combinaison d'objets que vous mettez dans une parcelle occupant plus de 1 Mo d'espace sera corrompu de l'autre côté. Cela peut être difficile à découvrir, alors gardez à l'esprit le type d'objets que vous envisagez de rendre parcellable. S'ils disposent de grands arbres de dépendance, envisagez un autre moyen de transmettre des données.
Rendre un objet personnalisé Parcelable.
/**
* Created by Alex Sullivan on 7/21/16.
*/
public class Foo implements Parcelable
{
private final int myFirstVariable;
private final String mySecondVariable;
private final long myThirdVariable;
public Foo(int myFirstVariable, String mySecondVariable, long myThirdVariable)
{
this.myFirstVariable = myFirstVariable;
this.mySecondVariable = mySecondVariable;
this.myThirdVariable = myThirdVariable;
}
// Note that you MUST read values from the parcel IN THE SAME ORDER that
// values were WRITTEN to the parcel! This method is our own custom method
// to instantiate our object from a Parcel. It is used in the Parcelable.Creator variable we declare below.
public Foo(Parcel in)
{
this.myFirstVariable = in.readInt();
this.mySecondVariable = in.readString();
this.myThirdVariable = in.readLong();
}
// The describe contents method can normally return 0. It's used when
// the parceled object includes a file descriptor.
@Override
public int describeContents()
{
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags)
{
dest.writeInt(myFirstVariable);
dest.writeString(mySecondVariable);
dest.writeLong(myThirdVariable);
}
// Note that this seemingly random field IS NOT OPTIONAL. The system will
// look for this variable using reflection in order to instantiate your
// parceled object when read from an Intent.
public static final Parcelable.Creator<Foo> CREATOR = new Parcelable.Creator<Foo>()
{
// This method is used to actually instantiate our custom object
// from the Parcel. Convention dictates we make a new constructor that
// takes the parcel in as its only argument.
public Foo createFromParcel(Parcel in)
{
return new Foo(in);
}
// This method is used to make an array of your custom object.
// Declaring a new array with the provided size is usually enough.
public Foo[] newArray(int size)
{
return new Foo[size];
}
};
}
Objet parcellable contenant un autre objet parcellable
Un exemple de classe contenant une classe parcellable à l'intérieur:
public class Repository implements Parcelable {
private String name;
private Owner owner;
private boolean isPrivate;
public Repository(String name, Owner owner, boolean isPrivate) {
this.name = name;
this.owner = owner;
this.isPrivate = isPrivate;
}
protected Repository(Parcel in) {
name = in.readString();
owner = in.readParcelable(Owner.class.getClassLoader());
isPrivate = in.readByte() != 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeParcelable(owner, flags);
dest.writeByte((byte) (isPrivate ? 1 : 0));
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<Repository> CREATOR = new Creator<Repository>() {
@Override
public Repository createFromParcel(Parcel in) {
return new Repository(in);
}
@Override
public Repository[] newArray(int size) {
return new Repository[size];
}
};
//getters and setters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Owner getOwner() {
return owner;
}
public void setOwner(Owner owner) {
this.owner = owner;
}
public boolean isPrivate() {
return isPrivate;
}
public void setPrivate(boolean isPrivate) {
this.isPrivate = isPrivate;
}
}
Le propriétaire est juste une classe parcelable normale.
Utiliser Enums avec Parcelable
/**
* Created by Nick Cardoso on 03/08/16.
* This is not a complete parcelable implementation, it only highlights the easiest
* way to read and write your Enum values to your parcel
*/
public class Foo implements Parcelable {
private final MyEnum myEnumVariable;
private final MyEnum mySaferEnumVariableExample;
public Foo(Parcel in) {
//the simplest way
myEnumVariable = MyEnum.valueOf( in.readString() );
//with some error checking
try {
mySaferEnumVariableExample= MyEnum.valueOf( in.readString() );
} catch (IllegalArgumentException e) { //bad string or null value
mySaferEnumVariableExample= MyEnum.DEFAULT;
}
}
...
@Override
public void writeToParcel(Parcel dest, int flags) {
//the simple way
dest.writeString(myEnumVariable.name());
//avoiding NPEs with some error checking
dest.writeString(mySaferEnumVariableExample == null? null : mySaferEnumVariableExample.name());
}
}
public enum MyEnum {
VALUE_1,
VALUE_2,
DEFAULT
}
Ceci est préférable à (par exemple) en utilisant un ordinal, car l'insertion de nouvelles valeurs dans votre enum n'affectera pas les valeurs stockées précédemment