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

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

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 :


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!


5

Esto debería funcionar:

in.readTypedList(products, Product.CREATOR);

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ó.


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


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

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

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

     }

 }
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.