web-dev-qa-db-fra.com

Écrire une sous-classe de Parcelable dans une autre parcelle

J'ai une classe qui implémente l'interface Parcelable:

class A implements Parcelable {

}

J'ai une autre classe B qui contient un objet A comme variable d'instance. Dans la classe writeToPacel à l'intérieur B, je veux écrire l'objet B dans le Parcel:

class B implements Parcelable{

    public void writeToParcel(Parcel dest, int flags) {
        dest.write ??? 
    }
}

Comment puis-je l'écrire et le lire?

64
user4o01
class B implements Parcelable{
//lets assume you have A as a data member 

A obj;
public void writeToParcel(Parcel dest, int flags) {

        dest.writeParcelable(obj , flags);

    }
}

si vous voulez le lire, utilisez ceci

 obj = in.readParcelable(A.class.getClassLoader());
162
confucius

Une meilleure façon de gérer cela qui évite la réflexion serait d'appeler simplement le créateur statique dans le type cible comme ceci:

this.amazingObject = AmazingObject.CREATOR.createFromParcel(in);

et l'écrire dans le Parcelable en utilisant this.amazingObject.writeToParcel(Parcel, int)

En interne, lors de l'appel de readParcelable(ClassLoader) cela se produit:

public final <T extends Parcelable> T readParcelable(ClassLoader loader) {
    Parcelable.Creator<T> creator = readParcelableCreator(loader);
    if (creator == null) {
        return null;
    }
    if (creator instanceof Parcelable.ClassLoaderCreator<?>) {
        return ((Parcelable.ClassLoaderCreator<T>)creator).createFromParcel(this, loader);
    }
    return creator.createFromParcel(this);
}

Comme vous pouvez le voir, le dernier appel de cette méthode appelle simplement le bon Creator mais à l'intérieur de readParcelableCreator il y a beaucoup de réflexions que nous pouvons éviter en l'appelant directement directement.

Cet appel d'utilitaire peut être utile:

import Android.os.Parcel;
import Android.os.Parcelable;

public class Parcels {

    public static void writeBoolean(Parcel dest, Boolean value) {
        dest.writeByte((byte) (value != null && value ? 1 : 0));
    }

    public static Boolean readBoolean(Parcel in){
        return in.readByte() != 0;
    }

    public static void writeParcelable(Parcel dest, int flags, Parcelable parcelable) {
        writeBoolean(dest, parcelable == null);
        if (parcelable != null) {
            parcelable.writeToParcel(dest, flags);
        }
    }

    public static <T extends Parcelable> T readParcelable(Parcel in, Parcelable.Creator<T> creator) {
        boolean isNull = readBoolean(in);
        return isNull ? null : creator.createFromParcel(in);
    }

}
11
pablisco

La ligne:

obj = (A)in.readParcelable(A.class.getClassLoader());

devrait changer en:

obj = (A)in.readParcelable(B.class.getClassLoader());

J'ai rencontré le même problème et j'ai effectué plusieurs recherches sur Google, de nombreuses pages Web ou didacticiels suggèrent que nous utilisons A.class.getClassLoader() parce que nous convertissons en A, mais en fait, il est faux car vous obtiendrez une valeur nulle, nous devons utiliser B.class.getClassLoader() car le codes are INSIDE class B. Je ne savais tout simplement pas pourquoi, mais il peut obtenir le bon objet A de cette façon.

Bienvenue pour commenter et vérifier !!

2
Alison