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 ???????;
    }
}

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());

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 :


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!


5

Cela devrait fonctionner:

in.readTypedList(products, Product.CREATOR);

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.


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


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);
    }

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());

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);

     }

 }
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.