¿Cómo pasar un objeto parcelable que contiene una lista de objetos?

96

He creado una Parcelablecontinuación objeto, mi objeto contiene una Listde los productos. En mi constructor, ¿cómo puedo volver a crear mi Parcelablepara el List?

He comprobado todos los métodos disponibles en el paquete y todo lo que está disponible es readArrayList(ClassLoader). No estoy seguro de si este es el mejor enfoque, su consejo sería muy apreciado.

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
fuente
¿Y qué pasa con readList()?
Alex Gitelman
El método readList (List, ClassLoader) en el tipo Parcel no es aplicable para los argumentos ()
Byron
No hay nada de malo en los argumentos. Así es como se utilizan a menudo las listas. Agregué respuesta.
Alex Gitelman

Respuestas:

102

Si la clase Productes compatible con el protocolo parcelable, lo siguiente debería funcionar de acuerdo con la documentación.

products = new ArrayList<Product>();
in.readList(products, Product.class.getClassLoader());
Alex Gitelman
fuente
No necesariamente. La documentación indica que writeList()escribirán objetos de acuerdo con las especificaciones descritas por writeValue()método. developer.android.com/reference/android/os/… Entre otras cosas, dice que el objeto puede ser serializable. readList()es contraparte writeList()y leerá los mismos datos.
Alex Gitelman
6
@AlexGitelman Pero el uso de la serialización se considera malo para el rendimiento, por eso hicieron que Parcable estuviera disponible, ¿no sería eso inútil?
eric.itzhak
30
No tuve suerte al usar esta solución tal como está. El ClassLoader de nulo in.readList(products,null);, obteniendo excepciones como ... Causado por: android.os.BadParcelableException: ClassNotFoundException al desagrupar: com.example.MyApplication.Product. La variación para leer la lista que realmente me funciona esin.readList(products,Product.class.getClassLoader());
Peter Dietz
2
Además, no olvide que el producto debe implementar Serializable
agmezr
40

Primero, su objeto Producto debe implementarse Parcelable.

Y luego, use dest.writeTypedList(products)en writeToParcel()método.

Finalmente, use el siguiente código para analizar la lista:

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

Para obtener más información, consulte el documento oficial :

codezjx
fuente
6

En mi experiencia personal, http://www.parcelabler.com/ es un sitio increíble para esto. Simplemente cree su clase, cópiela y péguela en el sitio web, y generará una versión Parcelable de su clase.

Lo probé con una clase llamada "Tema" que contenía las siguientes variables:

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

La función writeToParcel se convierte en:

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

constructor generado:

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

EDITAR: ¡asegúrese de que el objeto Tarjeta también sea Parcelable!

Pieter Desseyn
fuente
5

Esto debería funcionar:

in.readTypedList(products, Product.CREATOR);
usuario3875399
fuente
1
Me está creando problemas, esto funciona mejor: products = new ArrayList<Product>(); in.readList(products, Product.class.getClassLoader());
Shyam Sunder
1

implementar también Parcelableen la clase Product y luego

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

si alguna de las soluciones anteriores no funcionó.

Faisal Naseer
fuente
1

La otra forma es usar readValue y writeValue .

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

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

Los elementos de la lista deben implementar Parcelable

Negro arco iris
fuente
1

Aqui tienes...

Asegúrese de que "Products.java" se debe ampliar con Parcelable

Paso 1:

 private List<Products> products; 

Paso 2:

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

Paso 3:

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

Suponiendo que se Productestá implementando Parcelable, puede usar esto para escribir:

dest.writeValue(products);

y esto para leer:

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

El producto debe ser implementos Parcelable

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

Luego escribe que el objeto contiene una lista como

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
fuente