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


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.