Як передати об'єкт, що розширюється, який містить список об’єктів?


96

Я створив Parcelableоб’єкт нижче, мій об’єкт містить Listпродукти. Як в моєму конструкторі я можу впоратися із тим, щоб відновити своє Parcelableдля List?

Я перевірив усі методи, доступні для посилки, і все, що є, є readArrayList(ClassLoader). Я не впевнений, що це найкращий підхід, ваші поради дійсно будуть вдячні.

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

А що не так readList()?
— Alex Gitelman,

Метод readList (Список, ClassLoader) у типі Parcel не застосовується для аргументів ()
— Байрон

Нічого поганого в аргументах. Ось так часто використовуються списки. Я додав відповідь.
— Алекс Гітельман

Відповіді:


102

Якщо клас Productсумісний з протоколом посилки, наступний має працювати відповідно до документації.

products = new ArrayList<Product>();
in.readList(products, Product.class.getClassLoader());

Не обов'язково. Документація повідомляє, що writeList()записуватиме об'єкти відповідно до специфікацій, описаних writeValue()методом. developer.android.com/reference/android/os/… Серед іншого йдеться про те, що об’єкт може бути серіалізаційним. readList()є аналогом writeList()і буде читати ті самі дані.
— Алекс Гітельман

6
@AlexGitelman Але використання серіалізації вважається поганим для попередньої підготовки, тож саме тому вони зробили доступним Parcable, чи не зробить це безглуздим?
— eric.itzhak

30
Мені не пощастило використовувати це рішення як є. ClassLoader null in.readList(products,null);, отримуючи винятки, як ... Викликано: android.os.BadParcelableException: ClassNotFoundException при видаленні: com.example.MyApplication.Product. Варіант читання списку, який насправді працює для мене,in.readList(products,Product.class.getClassLoader());
— Пітер Дієц

2
Також не забувайте, що Продукт повинен реалізовувати Serializable
— agmezr

40

По-перше, ваш об’єкт Product повинен реалізовувати Parcelable .

А потім, використовуйте dest.writeTypedList(products)в writeToParcel()методі.

Нарешті, використовуйте наступний код для синтаксичного аналізу списку:

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

Для отримання додаткової інформації, будь ласка, зверніться до офіційного документа :


6

З мого особистого досвіду, http://www.parcelabler.com/ - це чудовий сайт для цього. Ви просто створіть свій клас і скопіюйте його, вставте його на веб-сайт, і він генерує версію для парцеляції вашого класу.

Я перевірив це за допомогою класу "Тема", який містив такі змінні:

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

Функція writeToParcel стає:

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

створений конструктор:

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

РЕДАГУВАТИ: переконайтесь, що об’єкт Картки також можна Парцелювати!


5

Це має працювати:

in.readTypedList(products, Product.CREATOR);

1
Це створює для мене проблеми, це працює краще: products = new ArrayList<Product>(); in.readList(products, Product.class.getClassLoader());
— Shyam Sunder,

1

реалізовуйте і Parcelableв класі Product, а потім

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

якщо жодне з перерахованих вище рішень не спрацювало.


1

Інший спосіб - використовувати readValue & writeValue .

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

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

Елементи списку повинні реалізовувати Parcelable


1

Ось ви йдете ...

Переконайтеся, що "Products.java" має бути розширено Parcelable

Крок 1:

 private List<Products> products; 

Крок 2:

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

Крок 3:

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

0

Припускаючи, що Productреалізується Parcelable, ви можете використовувати це для написання:

dest.writeValue(products);

і це для читання:

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

0

Продукт повинен бути реалізований парцелябельним

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

Потім запишіть, що об'єкт містить список, як

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

     }

 }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.