Wie übergebe ich ein Paketobjekt, das eine Liste von Objekten enthält?

95

Ich habe Parcelableunten ein Objekt erstellt, mein Objekt enthält ein ListProdukt. Wie gehe ich in meinem Konstruktor damit um, mein Parcelablefür das neu zu erstellen List?

Ich habe alle im Paket verfügbaren Methoden überprüft und alles, was verfügbar ist, ist readArrayList(ClassLoader). Ich bin mir nicht sicher, ob dies der beste Ansatz ist. Ihr Rat wäre wirklich dankbar.

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
quelle
Und was ist los mit readList()?
Alex Gitelman
Die Methode readList (List, ClassLoader) im Typ Parcel gilt nicht für die Argumente ()
Byron
An Argumenten ist nichts auszusetzen. So werden häufig Listen verwendet. Ich habe eine Antwort hinzugefügt.
Alex Gitelman

Antworten:

101

Wenn die Klasse Productmit dem Paketprotokoll kompatibel ist, sollte das Folgende gemäß der Dokumentation funktionieren.

products = new ArrayList<Product>();
in.readList(products, Product.class.getClassLoader());
Alex Gitelman
quelle
Nicht unbedingt. In der Dokumentation wird angegeben, dass writeList()Objekte gemäß den von der writeValue()Methode beschriebenen Spezifikationen geschrieben werden. developer.android.com/reference/android/os/… Unter anderem heißt es, dass das Objekt serialisierbar sein kann. readList()ist das Gegenstück zu writeList()und liest dieselben Daten.
Alex Gitelman
6
@AlexGitelman Aber die Verwendung von Serialisierung wird als schlecht für die Leistung angesehen. Deshalb haben sie Parcable zur Verfügung gestellt. Wäre das nicht sinnlos?
Eric.itzhak
30
Ich hatte kein Glück, diese Lösung so wie sie ist zu verwenden. Der ClassLoader von null in.readList(products,null);, der Ausnahmen wie ... abruft. Auslöser: android.os.BadParcelableException: ClassNotFoundException beim Aufheben der Marshalling-Funktion: com.example.MyApplication.Product. Die Variation, um die Liste zu lesen, die tatsächlich für mich funktioniert, istin.readList(products,Product.class.getClassLoader());
Peter Dietz
2
Vergessen Sie auch nicht, dass das Produkt Serializable implementieren muss
agmezr
40

Zunächst muss Ihr Produktobjekt implementiert werden Parcelable.

Und dann dest.writeTypedList(products)in writeToParcel()Methode verwenden.

Verwenden Sie zum Schluss den folgenden Code, um die Liste zu analysieren:

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

Weitere Informationen finden Sie im offiziellen Dokument :

codezjx
quelle
6

Nach meiner persönlichen Erfahrung ist http://www.parcelabler.com/ eine erstaunliche Website dafür. Sie erstellen einfach Ihre Klasse und kopieren sie, fügen sie in die Website ein und es wird eine Paketversion Ihrer Klasse generiert.

Ich habe es mit einer Klasse namens "Theme" getestet, die die folgenden Variablen enthielt:

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

Die Funktion writeToParcel lautet:

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

generierter Konstruktor:

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

BEARBEITEN: Stellen Sie sicher, dass das Kartenobjekt auch paketierbar ist!

Pieter Desseyn
quelle
5

Das sollte funktionieren:

in.readTypedList(products, Product.CREATOR);
user3875399
quelle
1
Es schafft Probleme für mich, das funktioniert besser: products = new ArrayList<Product>(); in.readList(products, Product.class.getClassLoader());
Shyam Sunder
1

auch Parcelablein der Produktklasse implementieren und dann

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

wenn eine der oben genannten Lösungen nicht funktioniert hat.

Faisal Naseer
quelle
1

Die andere Möglichkeit ist die Verwendung von readValue & writeValue .

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

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

Elemente der Liste sollten Parcelable implementieren

BlackRainbow
quelle
1

Bitte schön...

Stellen Sie sicher, dass "Products.java" mit Parcelable erweitert werden sollte

Schritt 1:

 private List<Products> products; 

Schritt 2:

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

Schritt 3:

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

Angenommen, das Productwird implementiert Parcelable, können Sie dies zum Schreiben verwenden:

dest.writeValue(products);

und das zum lesen:

products = (List<Product>) in.readValue(Product.class.getClassLoader());
Arenaq
quelle
0

Produkt muss Geräte Paketierbar sein

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

Dann schreiben Sie Ihr Objekt enthält Liste wie

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
quelle