web-dev-qa-db-fra.com

comment implémenter correctement Parcelable avec un ArrayList <Parcelable>?

J'ai du mal à faire ma classe Parcelable. Le problème est que j'essaie d'écrire au colis un membre de la classe qui est un ArrayList<Parcelable> objet. ArrayList est Serializable et les objets (ZigBeeDev) dans la liste sont Parcelable.

Voici le code pertinent:

package com.gnychis.coexisyst;

import Java.util.ArrayList;
import Java.util.Iterator;

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

public class ZigBeeNetwork implements Parcelable {

    public String _mac;             // the source address (of the coordinator?)
    public String _pan;             // the network address
    public int _band;               // the channel
    ArrayList<Integer> _lqis;       // link quality indicators (to all devices?)
    ArrayList<ZigBeeDev> _devices;  // the devices in the network

    public void writeToParcel(Parcel out, int flags) {
        out.writeString(_mac);
        out.writeString(_pan);
        out.writeInt(_band);
        out.writeSerializable(_lqis);
        out.writeParcelable(_devices, 0);  // help here
    }

    private ZigBeeNetwork(Parcel in) {
        _mac = in.readString();
        _pan = in.readString();
        _band = in.readInt();
        _lqis = (ArrayList<Integer>) in.readSerializable();
        _devices = in.readParcelable(ZigBeeDev.class.getClassLoader());  // help here
    }

    public int describeContents() {
        return this.hashCode();
    }

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

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

    //...
}

J'ai marqué deux points "// help here" pour comprendre comment écrire correctement sur le colis et comment le reconstruire. Si ZigBeeDev est Parcelable (correctement testé), comment dois-je procéder correctement?

75
gnychis

Vous l'avez presque compris!

Il vous suffit de faire:

public void writeToParcel(Parcel out, int flags) {
    out.writeString(_mac);
    out.writeString(_pan);
    out.writeInt(_band);
    out.writeSerializable(_lqis);
    out.writeTypedList(_devices);
}

private ZigBeeNetwork(Parcel in) {
    _mac = in.readString();
    _pan = in.readString();
    _band = in.readInt();
    _lqis = (ArrayList<Integer>) in.readSerializable();
    in.readTypedList(_devices, ZigBeeDev.CREATOR);
}

C'est tout!

Pour votre liste d'Integer, vous pouvez également faire:

out.writeList(_lqis);
_lqis = new ArrayList<>();
in.readList(_lqis Integer.class.getClassLoader());

Ça devrait marcher.

141
NitroG42

Dans mon cas, in.readTypedList(_devices, ZigBeeDev.CREATOR); m'a donné un NullPointerException sur _devices. J'ai donc utilisé ceci:

_devices = in.createTypedArrayList(ZigBeeDev.CREATOR);
17
osrl

Vous devez utiliser writeList (List l) pour votre liste d'entiers et writeTypedList (List val) pour la liste de ZigBeeDevices

8
DoubleMalt

Dans constructeur, vous devez utiliser

_lqis = in.createTypedArrayList(ZigBeeDev.CREATOR);

Et dans l'utilisation de "writeToParcel"

out.writeTypedList(_lqis);
2
Anton Smirnov

Un peu tard mais j'ai aussi eu ce problème. Après une longue perte de temps, je suis tombé sur le site parcelabler.com qui crée automatiquement des colis pour vous.

Cela m'a permis de créer très facilement une parcelle imbriquée contenant une liste de tableaux et m'a fait gagner beaucoup de temps.

Fondamentalement, le fonctionnement du site Web consiste à saisir votre objet avec la liste de tableaux et il ajoute automatiquement les méthodes nécessaires pour le rendre parcellable (lire à partir de parcelle, écrire sur parcelle, décrire le contenu et Créateur de parcelle sont tous générés automatiquement). Cela est particulièrement utile lors de la création de parcelles complexes, telles que la question posée ici, qui contiennent des parcelles, des tableaux et des listes imbriqués.

EDIT: Aussi IntelliJ IDEA et Android Studio a des plugins pour cela qui font une chose similaire au site Web répertorié:

Ces plugins génèrent Android Parcelable code passe-partout basé sur les champs de la classe.

0
JFreeman