Comment passer un objet parcellable contenant une liste d'objets?

96

J'ai créé un Parcelableobjet ci-dessous, mon objet contient un Listdes produits. Dans mon constructeur, comment gérer la recréation de mon Parcelablepour le List?

J'ai vérifié toutes les méthodes disponibles à partir du colis et tout ce qui est disponible est readArrayList(ClassLoader). Je ne sais pas si c'est la meilleure approche, vos conseils seraient vraiment appréciés.

public class Outfits implements Parcelable {

    private String url;
    private String name;
    private List<Product> products;

    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public List<Product> getProducts() {
        return products;
    }
    public void setProducts(List<Product> products) {
        this.products = products;
    }

    public void writeToParcel(Parcel dest, int flags) {
        Log.v("", "writeToParcel..." + flags);
        dest.writeString(url);
        dest.writeString(name);
        dest.writeList(products);
    }


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

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

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

    /*** Here how do I populate my List of Products ***/
    private Outfits(Parcel in) {
        url = in.readString();
        name = in.readString();
        products = in.read ???????;
    }
}
Byron
la source
Et quel est le problème readList()?
Alex Gitelman
La méthode readList (List, ClassLoader) dans le type Parcel n'est pas applicable pour les arguments ()
Byron
Rien de mal avec les arguments. C'est ainsi que les listes sont souvent utilisées. J'ai ajouté une réponse.
Alex Gitelman

Réponses:

102

Si la classe Productest compatible avec le protocole parcelable, la suite devrait fonctionner conformément à la documentation.

products = new ArrayList<Product>();
in.readList(products, Product.class.getClassLoader());
Alex Gitelman
la source
Pas nécessairement. La documentation indique que writeList()les objets écriront selon les spécifications décrites par la writeValue()méthode. developer.android.com/reference/android/os/... Entre autres, il indique que l'objet peut être sérialisable. readList()est la contrepartie writeList()et lira les mêmes données.
Alex Gitelman
6
@AlexGitelman Mais l'utilisation de la sérialisation est considérée comme mauvaise pour la préformance, c'est pourquoi ils ont rendu Parcable disponible, ne serait-ce pas un doigté qui rend cela inutile?
eric.itzhak
30
Je n'ai pas eu de chance d'utiliser cette solution telle quelle. Le ClassLoader de null in.readList(products,null);, obtenant des exceptions telles que ... Causé par: android.os.BadParcelableException: ClassNotFoundException lors de l'annulation de l'analyse: com.example.MyApplication.Product. La variante pour lire la liste qui fonctionne réellement pour moi estin.readList(products,Product.class.getClassLoader());
Peter Dietz
2
N'oubliez pas non plus que le produit doit implémenter Serializable
agmezr
40

Tout d'abord, votre objet Product doit implémenter Parcelable .

Et puis, utilisez dest.writeTypedList(products)danswriteToParcel() méthode.

Enfin, utilisez le code suivant pour analyser la liste:

products = new ArrayList<Product>();
in.readTypedList(products, Product.CREATOR);

Pour plus d'informations, veuillez consulter le document officiel :

codezjx
la source
6

D'après mon expérience personnelle, http://www.parcelabler.com/ est un site incroyable pour cela. Il vous suffit de créer votre classe, de la copier-coller dans le site Web et de générer une version parcellable de votre classe.

Je l'ai testé avec une classe nommée "Theme" qui contenait les variables suivantes:

private String name;
private int image;
private List<Card> cards;

La fonction writeToParcel devient:

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(name);
    dest.writeInt(image);
    if (cards == null) {
        dest.writeByte((byte) (0x00));
    } else {
        dest.writeByte((byte) (0x01));
        dest.writeList(cards);
    }
}

constructeur généré:

protected Theme(Parcel in) {
    name = in.readString();
    image = in.readInt();
    if (in.readByte() == 0x01) {
        cards = new ArrayList<Card>();
        in.readList(cards, Card.class.getClassLoader());
    } else {
        cards = null;
    }
}

EDIT: assurez-vous que l'objet Carte est également Colisable!

Pieter Desseyn
la source
5

Cela devrait fonctionner:

in.readTypedList(products, Product.CREATOR);
user3875399
la source
1
Cela me crée des problèmes, cela fonctionne mieux: products = new ArrayList<Product>(); in.readList(products, Product.class.getClassLoader());
Shyam Sunder
1

implémenter également Parcelablesur la classe Product, puis

in.readList(this.list, Product.class.getClassLoader());

si l'une des solutions ci-dessus ne fonctionne pas.

Faisal Naseer
la source
1

L'autre façon consiste à utiliser readValue et writeValue .

protected Product (Parcel in) {
        ...
        in.readValue(this.getClass().getClassLoader());
    }

@Override
public void writeToParcel(Parcel parcel, int i) {
    ...
    parcel.writeValue(**list**);
}

Les éléments de la liste doivent implémenter Parcelable

Noir arc en ciel
la source
1

Voici...

Assurez-vous que "Products.java" doit être étendu avec Parcelable

Étape 1:

 private List<Products> products; 

Étape 2:

private Outfits(Parcel in) {
    products = in.createTypedArrayList(Products.CREATOR);
}

Étape 3:

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeTypedList(products);
    }
Shyam Kumar
la source
0

En supposant que l' Productimplémentation est mise en œuvre Parcelable, vous pouvez l'utiliser pour écrire:

dest.writeValue(products);

et ceci pour lire:

products = (List<Product>) in.readValue(Product.class.getClassLoader());
arenaq
la source
0

Le produit doit être des outils Colisable

  Product class implements  Parcelable {
          ......
  }

Ensuite, écrivez votre objet contient une liste comme

public class Outfits implements Parcelable {

     private String url;
     private String name;
     private List<Product> products;

     public Outfits (Parcel pi) {

        bookName = p.readString();
        bookId = p.readInt();
        isColor = p.readInt() == 1;

        //use this well be get err
        //products=p.readArrayList(Thread.currentThread().getContextClassLoader());

        //Pass list use this 
        products= in.createTypedArrayList(Product.CREATOR);

      }

            ...get and set...

     public void writeToParcel(Parcel dest, int flags) {


        dest.writeString(url);
        dest.writeString(name);

        //use this will no working
        //dest.writeList(products);

        //Parcelable list
        out.writeTypedList(products);

     }

 }
Ven Ren
la source