Como posso tornar meus objetos personalizados Parceláveis?

338

Estou tentando fazer meus objetos serem paráveis. No entanto, tenho objetos personalizados e esses objetos têm ArrayListatributos de outros objetos personalizados que criei.

Qual seria a melhor forma de fazer isso?

Jean Jimenez
fonte

Respostas:

431

Você pode encontrar alguns exemplos disso aqui , aqui (o código é obtido aqui) e aqui .

Você pode criar uma classe POJO para isso, mas precisa adicionar um código extra para fazê-lo Parcelable. Dê uma olhada na implementação.

public class Student implements Parcelable{
        private String id;
        private String name;
        private String grade;

        // Constructor
        public Student(String id, String name, String grade){
            this.id = id;
            this.name = name;
            this.grade = grade;
       }
       // Getter and setter methods
       .........
       .........

       // Parcelling part
       public Student(Parcel in){
           String[] data = new String[3];

           in.readStringArray(data);
           // the order needs to be the same as in writeToParcel() method
           this.id = data[0];
           this.name = data[1];
           this.grade = data[2];
       }

       verride
       public int describeContents(){
           return 0;
       }

       @Override
       public void writeToParcel(Parcel dest, int flags) {
           dest.writeStringArray(new String[] {this.id,
                                               this.name,
                                               this.grade});
       }
       public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
           public Student createFromParcel(Parcel in) {
               return new Student(in); 
           }

           public Student[] newArray(int size) {
               return new Student[size];
           }
       };
   }

Depois de criar essa classe, você pode facilmente passar objetos dessa classe por esse Intenttipo e recuperar esse objeto na atividade de destino.

intent.putExtra("student", new Student("1","Mike","6"));

Aqui, o aluno é a chave necessária para desagrupar os dados do pacote.

Bundle data = getIntent().getExtras();
Student student = (Student) data.getParcelable("student");

Este exemplo mostra apenas Stringtipos. Mas você pode agrupar qualquer tipo de dados que desejar. Experimente.

EDIT: Outro exemplo , sugerido por Rukmal Dias .

ficção
fonte
@Rukmal Dias 10x. Na verdade, preciso editar minha resposta e adicionar algum código, porque esses links não estarão mais ativos algum dia no futuro.
ficção
16
OP perguntando como passar objetos personalizados e não sequência regular. Qualquer um pode passar cordas regulares. Você poderia explicar como criá-lo com CUSTOM OBJECT
Preciso realmente implementar as partes de codificação / decodificação se eu as enviar apenas usando o LocalBroadcastManager? É suficiente implementar Parcelable e colocar como extra?
JohnyTex
Por que você usa uma matriz de strings em vez de apenas escrever as strings sucessivamente?
Quentin Roy
A ordem dos membros ao criar a matriz de cadeias dentro do writeToParcelmétodo é importante?
Prakhar Mohan Srivastava
193

Aqui está um site para criar uma classe Parcelable a partir da sua classe criada:

http://www.parcelabler.com/

francisco_ssb
fonte
56

1. Importação Android Parcelable code generator

insira a descrição da imagem aqui

2. Crie uma classe

public class Sample {
    int id;
    String name;
}

3. Gerar> Parcelável no menu

insira a descrição da imagem aqui insira a descrição da imagem aqui

Feito.

kenju
fonte
7
Para quem não sabe onde está a caixa de diálogo Procurar Repositórios: File > Settings... > Pluginse clique no Browse repositories...botão.
DaedalusAlpha #
Obrigado, ajudou muito!
Strahinja Ajvaz
21

Quão? Com anotações.

Você simplesmente anota um POJO com uma anotação especial e a biblioteca faz o resto.

Atenção!

Não tenho certeza de que Hrisey, Lombok e outras bibliotecas de geração de código sejam compatíveis com o novo sistema de compilação do Android. Eles podem ou não funcionar bem com o código de troca quente (por exemplo, jRebel, Instant Run).

Prós:

  • As bibliotecas de geração de código salvam você do código-fonte padrão.
  • As anotações tornam sua classe bonita.

Contras:

  • Funciona bem para aulas simples. Tornar uma classe complexa parcelável pode ser complicado.
  • Lombok e AspectJ não tocam bem juntos. [detalhes]
  • Veja meus avisos.

Hrisey

Atenção!

Hrisey tem um problema conhecido com o Java 8 e, portanto, não pode ser usado atualmente no desenvolvimento do Android. Consulte # 1 Não foi possível encontrar erros de símbolo (JDK 8) .

Hrisey é baseado em Lombok . Classe Parcelable usando Hrisey :

@hrisey.Parcelable
public final class POJOClass implements android.os.Parcelable {
    /* Fields, accessors, default constructor */
}

Agora você não precisa implementar nenhum método da interface Parcelable. Hrisey irá gerar todo o código necessário durante a fase de pré-processamento.

Hrisey nas dependências de Gradle:

provided "pl.mg6.hrisey:hrisey:${hrisey.version}"

Veja aqui os tipos suportados. O ArrayListestá entre eles.

Instale um plug-in - Hrisey xor Lombok * - para o seu IDE e comece a usar seus incríveis recursos!

insira a descrição da imagem aqui
* Não ative os plug-ins Hrisey e Lombok juntos ou ocorrerá um erro durante o lançamento do IDE.


Parceler

Classe Parcelable usando o Parceler :

@java.org.parceler.Parcel
public class POJOClass {
    /* Fields, accessors, default constructor */
}

Para usar o código gerado, você pode referenciar a classe gerada diretamente ou através da Parcelsclasse utilidade usando

public static <T> Parcelable wrap(T input);

Para remover a referência @Parcel, basta chamar o seguinte método de Parcelsclasse

public static <T> T unwrap(Parcelable input);

Pacote nas dependências Gradle:

compile "org.parceler:parceler-api:${parceler.version}"
provided "org.parceler:parceler:${parceler.version}"

Procure no README os tipos de atributos suportados .


AutoParcel

AutoParcel é um AutoValue extensão do que permite a geração de valores Parcelable.

Basta adicionar implements Parcelableaos seus @AutoValuemodelos anotados:

@AutoValue
abstract class POJOClass implements Parcelable {
    /* Note that the class is abstract */
    /* Abstract fields, abstract accessors */

    static POJOClass create(/*abstract fields*/) {
        return new AutoValue_POJOClass(/*abstract fields*/);
    }
}

AutoParcel no arquivo de compilação Gradle:

apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'

repositories {
    /*...*/
    maven {url "https://clojars.org/repo/"}
}

dependencies {
    apt "frankiesardo:auto-parcel:${autoparcel.version}"
}

PaperParcel

O PaperParcel é um processador de anotação que gera automaticamente o código padrão do Parcelable seguro para tipos para Kotlin e Java. O PaperParcel suporta Classes de dados Kotlin, o AutoValue do Google por meio de uma extensão de AutoValue ou apenas objetos comuns de bean Java.

Exemplo de uso de documentos .
Anote sua classe de dados com @PaperParcel, implemente PaperParcelablee inclua uma instância estática da JVM, PaperParcelable.Creatorpor exemplo:

@PaperParcel
public final class Example extends PaperParcelable {
    public static final PaperParcelable.Creator<Example> CREATOR = new PaperParcelable.Creator<>(Example.class);

    private final int test;

    public Example(int test) {
        this.test = test;
    }

    public int getTest() {
        return test;
    }
}

Para usuários do Kotlin, consulte Uso do Kotlin ; Para usuários do AutoValue, consulte Uso do AutoValue .


ParcelableGenerator

ParcelableGenerator (o README está escrito em chinês e eu não o entendo. Contribuições para esta resposta de desenvolvedores que falam inglês-chinês são bem-vindas)

Exemplo de uso do README .

import com.baoyz.pg.Parcelable;

@Parcelable
public class User {

    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

}

O plug - in android-apt auxilia no trabalho com processadores de anotação em combinação com o Android Studio.

naXa
fonte
7

Eu encontrei a maneira mais simples de criar classe Parcelable

insira a descrição da imagem aqui

Rjz Satvara
fonte
11
ele funciona bem para dados pequeno, mas se levarmos dados complexos este não vai funcionar
Manohar Reddy
1

É muito fácil, você pode usar um plugin no android studio para fazer objetos Parcelables.

public class Persona implements Parcelable {
String nombre;
int edad;
Date fechaNacimiento;

public Persona(String nombre, int edad, Date fechaNacimiento) {
    this.nombre = nombre;
    this.edad = edad;
    this.fechaNacimiento = fechaNacimiento;
}

@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(this.nombre);
    dest.writeInt(this.edad);
    dest.writeLong(fechaNacimiento != null ? fechaNacimiento.getTime() : -1);
}

protected Persona(Parcel in) {
    this.nombre = in.readString();
    this.edad = in.readInt();
    long tmpFechaNacimiento = in.readLong();
    this.fechaNacimiento = tmpFechaNacimiento == -1 ? null : new Date(tmpFechaNacimiento);
}

public static final Parcelable.Creator<Persona> CREATOR = new Parcelable.Creator<Persona>() {
    public Persona createFromParcel(Parcel source) {
        return new Persona(source);
    }

    public Persona[] newArray(int size) {
        return new Persona[size];
    }
};}
App-SoftwareFactory
fonte
4
Qual plugin você quer dizer?
NaXa
0

Agora você pode usar a biblioteca Parceler para converter qualquer classe personalizada em parcelável. Apenas anote sua classe POJO com @Parcel . por exemplo

    @Parcel
    public class Example {
    String name;
    int id;

    public Example() {}

    public Example(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getName() { return name; }

    public int getId() { return id; }
}

você pode criar um objeto da classe Example e agrupar por meio de encomendas e enviar como um pacote por meio de intenção. por exemplo

Bundle bundle = new Bundle();
bundle.putParcelable("example", Parcels.wrap(example));

Agora, para obter o objeto Classe Personalizada, basta usar

Example example = Parcels.unwrap(getIntent().getParcelableExtra("example"));
Shubham Shukla
fonte
0

Pacote Android tem algumas coisas únicas. Estes são dados abaixo:

  1. Você deve ler o pacote na mesma ordem em que coloca os dados no pacote.
  2. O pacote será esvaziado após a leitura do pacote. Ou seja, se você tiver 3 dados no seu pacote. Então, depois de ler 3 vezes, o pacote estará vazio.

Exemplo: Para tornar uma classe Parceble, é necessário implementar a Parceble. Percable tem 2 métodos:

int describeContents();
void writeToParcel(Parcel var1, int var2);

Suponha que você tenha uma classe Person e ela possua 3 campos, firstName, lastName e age. Após implementar a interface Parceble. esta interface é apresentada abaixo:

import android.os.Parcel;
import android.os.Parcelable;
public class Person implements Parcelable{
    private String firstName;
    private String lastName;
    private int age;

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeString(firstName);
        parcel.writeString(lastName);
        parcel.writeInt(age);
    }

}

Aqui writeToParcelmétodo, estamos escrevendo / adicionando dados no Parcel em um pedido. Depois disso, temos que adicionar o código abaixo para ler os dados do pacote:

protected Person(Parcel in) {
        firstName = in.readString();
        lastName = in.readString();
        age = in.readInt();
    }

    public static final Creator<Person> CREATOR = new Creator<Person>() {
        @Override
        public Person createFromParcel(Parcel in) {
            return new Person(in);
        }

        @Override
        public Person[] newArray(int size) {
            return new Person[size];
        }
    };

Aqui, a classe Person está pegando um pacote e obtendo os dados na mesma ordem durante a gravação.

Agora, durante a intenção getExtraeputExtra código, é fornecido abaixo:

Colocar no Extra :

Person person=new Person();
                person.setFirstName("First");
                person.setLastName("Name");
                person.setAge(30);

                Intent intent = new Intent(getApplicationContext(), SECOND_ACTIVITY.class);
                intent.putExtra()
                startActivity(intent); 

Obter extra:

Person person=getIntent().getParcelableExtra("person");

A classe Full Person é dada abaixo :

import android.os.Parcel;
import android.os.Parcelable;

public class Person implements Parcelable{
    private String firstName;
    private String lastName;
    private int age;



    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeString(firstName);
        parcel.writeString(lastName);
        parcel.writeInt(age);
    }

    protected Person(Parcel in) {
        firstName = in.readString();
        lastName = in.readString();
        age = in.readInt();
    }

    public static final Creator<Person> CREATOR = new Creator<Person>() {
        @Override
        public Person createFromParcel(Parcel in) {
            return new Person(in);
        }

        @Override
        public Person[] newArray(int size) {
            return new Person[size];
        }
    };

}

Hope this will help you 
Thanks :)
Md. Sajedul Karim
fonte
0

Criar classe Parcelable sem plug-in no Android Studio

implementa Parcelable em sua classe e, em seguida, coloque o cursor em "implementa Parcelable" e pressione Alt+Entere selecione Add Parcelable implementation(veja a imagem). é isso aí.

insira a descrição da imagem aqui

Nagvadiya Vishal
fonte
-3

Colocar: bundle.putSerializable("key",(Serializable) object);

Para obter: List<Object> obj = (List<Object>)((Serializable)bundle.getSerializable("key"));

Macário
fonte
3
Isso levará a ClassCastExceptionse o objeto não for implementado Serializable.
NaXa
11
Embora esse trecho de código possa resolver a questão, incluir uma explicação realmente ajuda a melhorar a qualidade da sua postagem. Lembre-se de que você está respondendo à pergunta dos leitores no futuro e essas pessoas podem não saber os motivos da sua sugestão de código. Tente também não sobrecarregar seu código com comentários explicativos, pois isso reduz a legibilidade do código e das explicações!
Ashish Ahuja