¿Cómo puedo hacer mis objetos personalizados Parcelable?

338

Estoy tratando de hacer mis objetos Parcelable. Sin embargo, tengo objetos personalizados y esos objetos tienen ArrayListatributos de otros objetos personalizados que he creado.

Cuál sería la mejor forma de hacer esto?

Jean Jiménez
fuente

Respuestas:

431

Puede encontrar algunos ejemplos de esto aquí , aquí (el código se toma aquí) y aquí .

Puede crear una clase POJO para esto, pero necesita agregar un código adicional para hacerlo Parcelable. Echa un vistazo a la implementación.

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

Una vez que haya creado esta clase, puede pasar fácilmente objetos de esta clase a través de Intenteste tipo y recuperar este objeto en la actividad de destino.

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

Aquí, el alumno es la clave que necesitaría para desempaquetar los datos del paquete.

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

Este ejemplo muestra solo Stringtipos. Pero, puede parcelar cualquier tipo de datos que desee. Pruébalo.

EDITAR: Otro ejemplo , sugerido por Rukmal Dias .

ficción
fuente
@Rukmal Dias 10x. De hecho, debo editar mi respuesta y agregar un código, porque estos enlaces ya no estarán activos algún día en el futuro.
ficción
16
OP preguntando cómo pasar objetos personalizados no una cadena regular. Cualquiera puede pasar cadenas regulares. ¿Podría explicar CÓMO crearlo con OBJETO PERSONALIZADO
¿Tengo que implementar realmente las partes de codificación / decodificación si solo las envío usando LocalBroadcastManager? ¿Es suficiente implementar Parcelable y poner como extra?
JohnyTex
¿Por qué usas una matriz de cadenas en lugar de solo escribir las cadenas sucesivamente?
Quentin Roy
¿Importa el orden de los miembros al crear la matriz de cadenas dentro del writeToParcelmétodo?
Prakhar Mohan Srivastava
56

1. Importar Android Parcelable code generator

ingrese la descripción de la imagen aquí

2. Crea una clase

public class Sample {
    int id;
    String name;
}

3. Generar> Parcelable desde el menú

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

Hecho.

kenju
fuente
77
Para aquellos que no saben dónde está el cuadro de diálogo Examinar repositorios: File > Settings... > Pluginsy haga clic en el Browse repositories...botón.
DaedalusAlpha
¡Gracias, ayudó mucho!
Strahinja Ajvaz el
21

¿Cómo? Con anotaciones.

Simplemente anota un POJO con una anotación especial y la biblioteca hace el resto.

¡Advertencia!

No estoy seguro de que Hrisey, Lombok y otras bibliotecas de generación de código sean compatibles con el nuevo sistema de compilación de Android. Pueden o no jugar bien con el código de intercambio en caliente (es decir, jRebel, Instant Run).

Pros:

  • Las bibliotecas de generación de código lo salvan del código fuente repetitivo.
  • Las anotaciones hacen que tu clase sea hermosa.

Contras:

  • Funciona bien para clases simples. Hacer una clase compleja parcelable puede ser complicado.
  • Lombok y AspectJ no juegan bien juntos. [detalles]
  • Mira mis advertencias.

Hrisey

¡Advertencia!

Hrisey tiene un problema conocido con Java 8 y, por lo tanto, no se puede utilizar para el desarrollo de Android en la actualidad. Ver # 1 No se pueden encontrar errores de símbolo (JDK 8) .

Hrisey está basado en Lombok . Clase parcelable usando Hrisey :

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

Ahora no necesita implementar ningún método de interfaz Parcelable. Hrisey generará todo el código requerido durante la fase de preprocesamiento.

Hrisey en las dependencias de Gradle:

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

Consulte aquí los tipos compatibles. El ArrayListestá entre ellos.

Instale un complemento - Hrisey xor Lombok * - para su IDE y comience a usar sus increíbles funciones.

ingrese la descripción de la imagen aquí
* No habilite los complementos de Hrisey y Lombok juntos o recibirá un error durante el inicio de IDE.


Parceler

Clase parcelable usando Parceler :

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

Para usar el código generado, puede hacer referencia a la clase generada directamente o mediante la Parcelsclase de utilidad utilizando

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

Para desreferenciar @Parcel, simplemente llame al siguiente método de Parcelsclase

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

Parceler en dependencias de Gradle:

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

Busque en README los tipos de atributos admitidos .


AutoParcel

AutoParcel es una extensión de AutoValue que permite la generación de valores parcelables.

Simplemente agregue implements Parcelablea sus @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 en el archivo de compilación de 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

PaperParcel es un procesador de anotaciones que genera automáticamente código repetitivo parcelable seguro para Kotlin y Java. PaperParcel admite clases de datos de Kotlin, AutoValue de Google a través de una extensión de AutoValue o simplemente objetos Java Bean normales.

Ejemplo de uso de documentos .
Anote su clase de datos con @PaperParcel, implemente PaperParcelabley agregue una instancia estática de JVM, por PaperParcelable.Creatorejemplo:

@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 usuarios de Kotlin, vea Uso de Kotlin ; Para usuarios de AutoValue, consulte Uso de AutoValue .


Generador parcelable

ParcelableGenerator (README está escrito en chino y no lo entiendo. Las contribuciones a esta respuesta de desarrolladores de habla inglesa-china son bienvenidas)

Ejemplo de uso de 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;
    }

}

El complemento android-apt ayuda a trabajar con procesadores de anotaciones en combinación con Android Studio.

naXa
fuente
7

He encontrado la forma más sencilla de crear la clase Parcelable

ingrese la descripción de la imagen aquí

Rjz Satvara
fuente
1
funciona bien para datos pequeños, pero si tomamos datos complejos, esto no funcionará
Manohar Reddy
1

Es muy fácil, puede usar un complemento en Android Studio para hacer 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
fuente
44
¿A qué plugin te refieres?
naXa
0

Ahora puede usar la biblioteca Parceler para convertir cualquier clase personalizada en parcelable. Simplemente anote su clase POJO con @Parcel . p.ej

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

puede crear un objeto de clase Ejemplo y envolver paquetes y enviarlos como un paquete a través de la intención. p.ej

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

Ahora para obtener un objeto de clase personalizada solo use

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

Android parcable tiene algunas cosas únicas. Esos se dan a continuación:

  1. Debe leer Parcela como el mismo orden en el que coloca los datos en la parcela.
  2. El paquete se vaciará después de leerlo. Eso es si tiene 3 datos en su paquete. Luego, después de leer 3 veces, el paquete estará vacío.

Ejemplo: para hacer una clase Parceble, debe implementar Parceble. Percable tiene 2 métodos:

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

Supongamos que tiene una clase Persona y tiene 3 campos, nombre, apellido y edad. Después de implementar la interfaz Parceble. esta interfaz se muestra a continuación:

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

}

Aquí writeToParcelmétodo estamos escribiendo / agregando datos en Parcel en un pedido. Después de esto, debemos agregar el siguiente código para leer los datos del paquete:

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

Aquí, la clase Persona toma un paquete y obtiene datos en el mismo orden durante la escritura.

Ahora durante la intención getExtray el putExtracódigo se da a continuación:

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

Obtenga extra:

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

La clase de persona completa se da a continuación :

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
fuente
0

Crear clase Parcelable sin complemento en Android Studio

implementa Parcelable en su clase y luego coloca el cursor en "Implementa Parcelable" y presiona Alt+Entery selecciona Add Parcelable implementation(ver imagen). Eso es.

ingrese la descripción de la imagen aquí

Nagvadiya Vishal
fuente
-3

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

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

Macário
fuente
3
Esto conducirá a ClassCastExceptionsi el objeto no se implementa Serializable.
naXa
1
Si bien este fragmento de código puede resolver la pregunta, incluir una explicación realmente ayuda a mejorar la calidad de su publicación. Recuerde que está respondiendo la pregunta para los lectores en el futuro, y que esas personas podrían no conocer los motivos de su sugerencia de código. Por favor, trate de no saturar su código con comentarios explicativos, ¡esto reduce la legibilidad tanto del código como de las explicaciones!
Ashish Ahuja