Jak przekazać obiekt do spakowania zawierający listę obiektów?

96

Utworzyłem Parcelableobiekt poniżej, mój obiekt zawiera Listprodukty. W moim konstruktorze, jak poradzić sobie z ponownym tworzeniem pliku Parcelabledla List?

Sprawdziłem wszystkie metody dostępne w paczce i wszystko, co jest dostępne, jest readArrayList(ClassLoader). Nie jestem pewien, czy to najlepsze podejście, Twoja rada byłaby naprawdę wdzięczna.

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
źródło
A co jest nie tak readList()?
Alex Gitelman
Metoda readList (List, ClassLoader) w typie Parcel nie ma zastosowania dla argumentów ()
Byron
Nie ma nic złego w argumentach. Tak często używa się list. Dodałem odpowiedź.
Alex Gitelman

Odpowiedzi:

103

Jeśli klasa Productjest zgodna z protokołem parcelable to postępuj zgodnie z dokumentacją.

products = new ArrayList<Product>();
in.readList(products, Product.class.getClassLoader());
Alex Gitelman
źródło
Niekoniecznie. Dokumentacja stwierdza, że writeList()obiekty będą zapisywane zgodnie ze specyfikacjami opisanymi writeValue()metodą. developer.android.com/reference/android/os/… Między innymi mówi, że obiekt można serializować. readList()jest odpowiednikiem writeList()i będzie czytać te same dane.
Alex Gitelman
6
@AlexGitelman Ale używanie serializacji jest uważane za złe dla wydajności, więc dlatego udostępnili Parcable, czy nie zrobiłby tego, co czyni to bezcelowym?
eric.itzhak
30
Nie miałem szczęścia używając tego rozwiązania w obecnej postaci. ClassLoader o wartości null in.readList(products,null);, uzyskuje wyjątki, takie jak ... Spowodowane przez: android.os.BadParcelableException: ClassNotFoundException podczas cofania oceny: com.example.MyApplication.Product. Wariantem czytania listy, która faktycznie działa dla mnie, jestin.readList(products,Product.class.getClassLoader());
Peter Dietz,
2
Nie zapominaj również, że produkt musi zaimplementować Serializable
agmezr
40

Po pierwsze, obiekt Product musi implementować Parcelable .

A następnie użyć dest.writeTypedList(products)w writeToParcel()metodzie.

Na koniec użyj następującego kodu, aby przeanalizować listę:

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

Więcej informacji można znaleźć w oficjalnym dokumencie :

codezjx
źródło
6

Z mojego osobistego doświadczenia wynika , że http://www.parcelabler.com/ wynika jest do tego niesamowitą witryną. Po prostu tworzysz swoją klasę i kopiujesz ją wklejasz na stronę internetową, a to generuje wersję Twojej klasy Parcelable.

Przetestowałem to z klasą o nazwie „Motyw”, która zawierała następujące zmienne:

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

Funkcja writeToParcel zmienia się w:

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

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

EDYCJA: upewnij się, że obiekt Karta również nadaje się do paczkowania!

Pieter Desseyn
źródło
5

To powinno działać:

in.readTypedList(products, Product.CREATOR);
user3875399
źródło
1
Stwarza to dla mnie problemy, to działa lepiej: products = new ArrayList<Product>(); in.readList(products, Product.class.getClassLoader());
Shyam Sunder
1

zaimplementować również Parcelablew klasie Product, a następnie

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

jeśli którekolwiek z powyższych rozwiązań nie zadziałało.

Faisal Naseer
źródło
1

Innym sposobem jest użycie readValue i writeValue .

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

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

Pozycje listy powinny zawierać Parcelable

BlackRainbow
źródło
1

Proszę bardzo...

Upewnij się, że "Products.java" powinno zostać rozszerzone o Parcelable

Krok 1:

 private List<Products> products; 

Krok 2:

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

Krok 3:

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeTypedList(products);
    }
Shyam Kumar
źródło
0

Zakładając, że Productimplementuje się Parcelable, możesz użyć tego do napisania:

dest.writeValue(products);

a to do czytania:

products = (List<Product>) in.readValue(Product.class.getClassLoader());
arenaq
źródło
0

Produkt musi być narzędziami Parcelable

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

Następnie napisz, że obiekt zawiera listę, taką jak

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
źródło