Как передать посылочный объект, содержащий список объектов?


97

Я создал Parcelableобъект ниже, мой объект содержит Listиз Products. В моем конструкторе, как мне обработать повторное создание моего 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 (List, ClassLoader) в типе Parcel неприменим для arguments ()
Байрон

В аргументах нет ничего плохого. Вот как часто используются списки. Я добавил ответ.
Alex Gitelman

Ответы:


104

Если класс Productсовместим с протоколом parcelable, следующее должно работать в соответствии с документацией.

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

Не обязательно. В документации указано, что writeList()объекты будут писать в соответствии со спецификациями, описанными writeValue()методом. developer.android.com/reference/android/os/… Среди прочего в нем говорится, что объект может быть сериализуемым. readList()является аналогом writeList()и будет читать те же данные.
Alex Gitelman

6
@AlexGitelman Но использование сериализации считается плохим для преформования, поэтому они сделали доступным Parcable, разве это не делает это бессмысленным?
eric.itzhak 08

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)in writeToParcel()method.

Наконец, используйте следующий код для анализа списка:

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

Для получения дополнительной информации, пожалуйста, обратитесь к официальному документу :


6

По моему личному опыту, http://www.parcelabler.com/ - отличный сайт для этого. Вы просто создаете свой класс, копируете и вставляете его на веб-сайт, и он генерирует Parcelable версию вашего класса.

Я протестировал его с помощью класса «Theme», который содержал следующие переменные:

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

РЕДАКТИРОВАТЬ: убедитесь, что объект Card также является Parcelable!


5

Это должно работать:

in.readTypedList(products, Product.CREATOR);

1
Это создает для меня проблемы, это работает лучше: products = new ArrayList<Product>(); in.readList(products, Product.class.getClassLoader());
Шьям Сандер

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.