web-dev-qa-db-fra.com

Comment faire une classe avec des objets imbriqués Parcelable

J'aimerais faire la classe A Parcelable.

public class A {
    public String str;
    public ArrayList<B> list;
}

C'est ce que j'ai proposé jusqu'à présent. Cependant, il se bloque avec une exception NullPointerException. Le problème réside dans ces deux affirmations: dest.writeList(list); & in.readList(list, this.getClass().getClassLoader());. Je ne vois pas quoi faire à partir de cet endroit :(

Classe A

public class A implements Parcelable {
    public String str;
    public ArrayList<B> list;

    @Override
    public int describeContents() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(str);
        dest.writeList(list);
    }

    private A(Parcel in) {
        str = in.readString();
        in.readList(list, this.getClass().getClassLoader());
    }

    public static final Parcelable.Creator<A> CREATOR
            = new Parcelable.Creator<A>() {
        public A createFromParcel(Parcel in) {
            return new A(in);
        }

        public A[] newArray(int size) {
            return new A[size];
        }
    };
}

Classe B

public class B implements Parcelable {
    public String str;

    @Override
    public int describeContents() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(str);
    }

    private B(Parcel in) {
        str = in.readString();
    }

    public static final Parcelable.Creator<B> CREATOR
            = new Parcelable.Creator<B>() {
        public B createFromParcel(Parcel in) {
            return new B(in);
        }

        public B[] newArray(int size) {
            return new B[size];
        }
    };
}

Merci pour votre temps.

30
Snæbjørn

J'ai enfin compris quoi taper dans Google :), et j'ai trouvé ceci Android, Comment utiliser correctement la méthode readTypedList dans une classe Parcelable?

La solution consistait à utiliser read-/writeTypedList à la place. J'initialise également l'arraylist pour éviter toute autre exception NullPointerException.

Classe A

public class A implements Parcelable {
    public String str;
    public ArrayList<B> list = new ArrayList<B>();

    @Override
    public int describeContents() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(str);
        dest.writeTypedList(list);
    }

    private A(Parcel in) {
        str = in.readString();
        in.readTypedList(list, B.CREATOR);
    }

    public static final Parcelable.Creator<A> CREATOR
            = new Parcelable.Creator<A>() {
        public A createFromParcel(Parcel in) {
            return new A(in);
        }

        public A[] newArray(int size) {
            return new A[size];
        }
    };
}

Classe B

public class B implements Parcelable {
    public String str;

    @Override
    public int describeContents() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(str);
    }

    private B(Parcel in) {
        str = in.readString();
    }

    public static final Parcelable.Creator<B> CREATOR
            = new Parcelable.Creator<B>() {
        public B createFromParcel(Parcel in) {
            return new B(in);
        }

        public B[] newArray(int size) {
            return new B[size];
        }
    };
}
49
Snæbjørn

Si vous avez un seul objet Parcelabledans votre objet Parcelable principal, n'effectuez pas la liste comme dans le cas de réponse accepté. Ensuite, ce sera comme suit:

Classe A

public class A implements Parcelable {
    public String str;
    public B objectB;

    @Override
    public int describeContents() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        //The parcelable object has to be the first one
        dest.writeParcelable(objectB, flags);
        dest.writeString(str);
    }

    private A(Parcel in) {
        this.objectB = in.readParcelable(B.class.getClassLoader());
        str = in.readString();
    }

    public static final Parcelable.Creator<A> CREATOR
            = new Parcelable.Creator<A>() {
        public A createFromParcel(Parcel in) {
            return new A(in);
        }

        public A[] newArray(int size) {
            return new A[size];
        }
    };
}

Classe B

public class B implements Parcelable {
    public String str;

    @Override
    public int describeContents() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(str);
    }

    private B(Parcel in) {
        str = in.readString();
    }

    public static final Parcelable.Creator<B> CREATOR
            = new Parcelable.Creator<B>() {
        public B createFromParcel(Parcel in) {
            return new B(in);
        }

        public B[] newArray(int size) {
            return new B[size];
        }
    };
}

IMPORTANT: Veuillez noter que l'ordre dans lequel vous écrivez et lisez l'objet Parcelable est important. Commander cette réponse pour plus de détails

21
Sami Eltamawy

À écrire au colis

@Override
public void writeToParcel(Parcel parcel, int i) {
    parcel.writeString(name); //if String
    parcel.writeTypedList(assignedEmployees); //if List with custom class, eg. List<AssignedEmployee> assignedEmployees
    parcel.writeParcelable(checkin,i); //if custom class, eg. Checkin checkin;
    }

Au constructeur pour le relire

 protected A(Parcel in) {
        name = in.readString();
        assignedEmployees = in.createTypedArrayList(AssignedEmployee.CREATOR);
        checkin = in.readParcelable(Checkin.class.getClassLoader());
    }

où AssignedEmployee, Archiver où les classes personnalisées et il devrait implémenter Parcelable.

1
Ebin Joy

J'utilisais malheureusement une classe (BarEntry) d'une bibliothèque tierce qui n'a pas pu être parcellisée. J'ai résolu mon problème en passant par Intent un tableau de floats, puis en reconstruisant mes objets BarEntry à la réception.

Ceci est sous-optimal mais cela peut être un processus utile si quelqu'un se trouve dans une situation similaire où la création d'un objet pouvant faire l'objet d'une parcelle n'est pas une option. 

0
JFreeman

Appuyez simplement sur ALT + ENTRÉE et remplacez Parcelable, il implémentera toutes les implémentations nécessaires.

0
Dhruv Singh

J'ai eu le même problème voici une version générique

class Item<T : Parcelable> (val model: T, val index: Int ) : Parcelable {

    constructor(parcel: Parcel) :
        this(parcel.readParcelable(
          Item<T>::model.javaClass.classLoader),
          parcel.readInt()
        ) {}

    override fun writeToParcel(parcel: Parcel?, flag: Int) {
        parcel?.writeParcelable(model, 0)
        parcel?.writeInt(index)
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR : Parcelable.Creator<Item<Parcelable>> {
        override fun createFromParcel(parcel: Parcel): Item<Parcelable> {
            return Item(parcel)
        }

        override fun newArray(size: Int): Array<Item<Parcelable>?> {
            return arrayOfNulls(size)
        }
    }
}
0
Jocky Doe

Vous pouvez ajouter le plugin générateur de code parcellaire à partir de prefs, puis créer le code de plaque parcellaire de la chaudière en procédant comme suit: - clic droit sur le nom de la classe dans le modèle - sélectionner générer - sélectionnez Parcelable

presto - votre modèle sera mis à jour avec le code passe-partout nécessaire.

0
ScottishUser