Como passar um objeto parcelável que contém uma lista de objetos?

96

Eu criei um Parcelableobjeto abaixo, meu objeto contém um Listde Produtos. No meu construtor, como faço para recriar o meu Parcelablepara o List?

Eu verifiquei todos os métodos disponíveis no pacote e tudo o que está disponível é readArrayList(ClassLoader). Não tenho certeza se esta é a melhor abordagem, seu conselho seria realmente 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
fonte
E o que há de errado readList()?
Alex Gitelman
O método readList (List, ClassLoader) no tipo Parcel não é aplicável para os argumentos ()
Byron
Nada de errado com argumentos. É assim que as listas são freqüentemente usadas. Eu acrescentei a resposta.
Alex Gitelman

Respostas:

102

Se a classe Productfor compatível com o protocolo parcelable, o seguinte deve funcionar de acordo com a documentação.

products = new ArrayList<Product>();
in.readList(products, Product.class.getClassLoader());
Alex Gitelman
fonte
Não necessariamente. A documentação declara que writeList()escreverá objetos de acordo com as especificações descritas pelo writeValue()método. developer.android.com/reference/android/os/… Entre outras coisas, diz que o objeto pode ser serializável. readList()é a contrapartida writeList()e lerá os mesmos dados.
Alex Gitelman
6
@AlexGitelman Mas usar a serialização é considerado ruim para o desempenho, então é por isso que eles disponibilizaram o Parcable, isso não faria isso sem sentido?
eric.itzhak
30
Eu não estava tendo sorte ao usar essa solução como está. O ClassLoader de null in.readList(products,null);, obtendo exceções como ... Causado por: android.os.BadParcelableException: ClassNotFoundException ao desempacotar: com.example.MyApplication.Product. A variação para ler a lista que realmente funciona para mim éin.readList(products,Product.class.getClassLoader());
Peter Dietz
2
Também não se esqueça que o produto precisa implementar o Serializable
agmezr
40

Primeiro, seu objeto Produto deve implementar Parcelable.

E então, use dest.writeTypedList(products)no writeToParcel()método.

Por fim, use o seguinte código para analisar a lista:

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

Para obter mais informações, consulte o Documento Oficial :

codezjx
fonte
6

Em minha experiência pessoal, http://www.parcelabler.com/ é um site incrível para isso. Você apenas cria sua classe, copia e cola no site, e isso gera uma versão Parcelable de sua classe.

Eu testei com uma classe chamada "Theme" que continha as seguintes variáveis:

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

A função writeToParcel torna-se:

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

construtor gerado:

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: certifique-se de que o objeto Cartão também seja Parcelável!

Pieter Desseyn
fonte
5

Isso deve funcionar:

in.readTypedList(products, Product.CREATOR);
user3875399
fonte
1
Está criando problemas para mim, funciona melhor: products = new ArrayList<Product>(); in.readList(products, Product.class.getClassLoader());
Shyam Sunder
1

implementar Parcelablena classe de produto também e então

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

se alguma das soluções acima não funcionar.

Faisal Naseer
fonte
1

A outra maneira é usar readValue e writeValue .

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

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

Os itens da lista devem implementar Parcelable

BlackRainbow
fonte
1

Aqui está...

Certifique-se de que "Products.java" deve ser estendido com Parcelable

Passo 1:

 private List<Products> products; 

Passo 2:

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

Etapa 3:

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

Supondo que o Productesteja implementando Parcelable, você pode usar isso para escrever:

dest.writeValue(products);

e isto para leitura:

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

O produto deve ser implementos Parceláveis

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

Em seguida, escreva seu objeto contém 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
fonte