Android: ¿diferencia entre parcelable y serializable?

313

¿Por qué Android proporciona 2 interfaces para serializar objetos? ¿Los objetos serializables interactúan con los Binderarchivos Android y AIDL?

live2dream95
fuente

Respuestas:

444

En Android no podemos simplemente pasar objetos a actividades. Para hacer esto, los objetos deben implementarse Serializableo Parcelableinteractuar.

Serializable

Serializablees una interfaz estándar de Java. Simplemente puede implementar la Serializableinterfaz y agregar métodos de anulación. El problema con este enfoque es que se utiliza la reflexión y es un proceso lento. Este método crea muchos objetos temporales y causa bastante recolección de basura. Sin embargo, la Serializableinterfaz es más fácil de implementar.

Mira el ejemplo a continuación (serializable):

// MyObjects Serializable class

import java.io.Serializable;
import java.util.ArrayList;
import java.util.TreeMap;

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

public class MyObjects implements Serializable {

    private String name;
    private int age;
    public ArrayList<String> address;

    public MyObjects(String name, int age, ArrayList<String> address) {
        super();
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public ArrayList<String> getAddress() {
        if (!(address == null))
            return address;
        else
            return new ArrayList<String>();
    }

    public String getName() {
        return name;
    }

    public String getAge() {
        return age;
    }
}
// MyObjects instance
MyObjects mObjects = new MyObjects("name", "age", "Address array here");

// Passing MyObjects instance via intent
Intent mIntent = new Intent(FromActivity.this, ToActivity.class);
mIntent.putExtra("UniqueKey", mObjects);
startActivity(mIntent);
// Getting MyObjects instance
Intent mIntent = getIntent();
MyObjects workorder = (MyObjects)    mIntent.getSerializableExtra("UniqueKey");

Parcelable

ParcelableEl proceso es mucho más rápido que Serializable. Una de las razones de esto es que estamos siendo explícitos sobre el proceso de serialización en lugar de usar la reflexión para inferirlo. También es lógico pensar que el código ha sido muy optimizado para este propósito.

Mire el ejemplo a continuación (Parcelable):

// MyObjects Parcelable class

import java.util.ArrayList;

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

public class MyObjects implements Parcelable {

    private int age;
    private String name;
    private ArrayList<String> address;

    public MyObjects(String name, int age, ArrayList<String> address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public MyObjects(Parcel source) {
        age = source.readInt();
        name = source.readString();
        address = source.createStringArrayList();
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(age);
        dest.writeString(name);
        dest.writeStringList(address);
    }

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

    public ArrayList<String> getAddress() {
        if (!(address == null))
            return address;
        else
            return new ArrayList<String>();
    }

    public static final Creator<MyObjects> CREATOR = new Creator<MyObjects>() {
        @Override
        public MyObjects[] newArray(int size) {
            return new MyObjects[size];
        }

        @Override
        public MyObjects createFromParcel(Parcel source) {
            return new MyObjects(source);
        }
    };
}
// MyObjects instance
MyObjects mObjects = new MyObjects("name", "age", "Address array here");

// Passing MyOjects instance
Intent mIntent = new Intent(FromActivity.this, ToActivity.class);
mIntent.putExtra("UniqueKey", mObjects);
startActivity(mIntent);
// Getting MyObjects instance
Intent mIntent = getIntent();
MyObjects workorder = (MyObjects) mIntent.getParcelableExtra("UniqueKey");

Puede pasar ArrayListobjetos parcelables de la siguiente manera:

// Array of MyObjects
ArrayList<MyObjects> mUsers;

// Passing MyOjects instance
Intent mIntent = new Intent(FromActivity.this, ToActivity.class);
mIntent.putParcelableArrayListExtra("UniqueKey", mUsers);
startActivity(mIntent);
// Getting MyObjects instance
Intent mIntent = getIntent();
ArrayList<MyObjects> mUsers = mIntent.getParcelableArrayList("UniqueKey");

Conclusión

  1. Parcelablees más rápido que la Serializableinterfaz
  2. ParcelableLa interfaz tarda más tiempo en implementarse en comparación con la Serializableinterfaz
  3. Serializable la interfaz es más fácil de implementar
  4. Serializable La interfaz crea muchos objetos temporales y causa bastante recolección de basura
  5. Parcelable matriz se puede pasar a través de Intención en Android
Sujith
fuente
2
@Sujith, ¿qué quieres decir con reflexión ? ¿Qué es la reflexión ?
AnV
11
@AbhinavVutukuri Reflection es el término para inspeccionar objetos, campos y métodos en tiempo de ejecución a través de Object.getClass () y demás.
FaultException
2
Los serializables son mejores para datos persistentes, los objetos parcelables, por otro lado, no deberían persistirse en absoluto. Es una práctica realmente mala
TheAnimatrix
2
@Sujith Como ha dicho más de una persona, los objetos parcelables no pueden ser persistentes (de manera confiable) pero los serializables sí (dentro de los límites). Dado que su respuesta es la más alta y da la impresión de cubrir todas las diferencias importantes, probablemente debería mencionar ese punto.
LarsH
44
Ahora, la implementación de Parcelable es tan rápida como serializable, solo presione ALT + INSERTAR en cualquier clase que implemente Parcelable en Android Studio y el IDE lo hará.
Ali Nem
183

Serializable es una interfaz estándar de Java. Simplemente marque una clase Serializable implementando la interfaz, y Java la serializará automáticamente en ciertas situaciones.

Parcelable es una interfaz específica de Android donde implementa la serialización usted mismo. Fue creado para ser mucho más eficiente que Serializable, y para solucionar algunos problemas con el esquema de serialización Java predeterminado.

Creo que Binder y AIDL funcionan con objetos parcelables.

Sin embargo, puede usar objetos serializables en Intents.

Cheryl Simon
fuente
1
¿Cómo serializo un objeto Parcelable? ¿Cómo lo hago persistente?
Hades
@Haded Obtenga el contenido del estado de los objetos y guárdelo en un archivo o base de datos SQLLite. Seriliasing es útil para hacer que los objetos sean transferibles entre diferentes componentes en Android o diferentes aplicaciones por completo.
Jonathan
66
Esta es una gran explicación. También noté esto: "La parcela no es un mecanismo de serialización de propósito general. Esta clase (y la API Parcelable correspondiente para colocar objetos arbitrarios en una Parcela) está diseñada como un transporte IPC de alto rendimiento. Como tal, no es apropiado coloque los datos de Parcel en almacenamiento persistente: los cambios en la implementación subyacente de cualquiera de los datos en Parcel pueden hacer que los datos más antiguos sean ilegibles ". developer.android.com/reference/android/os/Parcel.html
Sam003
@Zhisheng, ¿qué se entiende por objetos arbitrarios? ¿Qué tipo de objetos podemos poner en el paquete?
hasnain_ahmad
¿Qué tal convertir objetos a cadenas json en lugar de gson?
FOO
57

Parcelable vs Serializable Me refiero a estos dos.

Para Java y Kotlin

1) Java

Serializable, la simplicidad

¿Qué es serializable?

Serializable es una interfaz estándar de Java. No es parte del SDK de Android. Su simplicidad es su belleza. Con solo implementar esta interfaz, su POJO estará listo para saltar de una Actividad a otra.

public class TestModel implements Serializable {

String name;

public TestModel(String name) {
    this.name = name;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}
}
  • La belleza de serializable es que solo necesita implementar la interfaz serializable en una clase y sus hijos. Es una interfaz de marcador, lo que significa que no hay un método para implementar, Java simplemente hará su mejor esfuerzo para serializarlo de manera eficiente.

  • El problema con este enfoque es que se utiliza la reflexión y es un proceso lento. Este mecanismo también tiende a crear una gran cantidad de objetos temporales y causa una gran cantidad de recolección de basura.

Parcelable, La Velocidad

¿Qué es parcelable?

Parcelable es otra interfaz. A pesar de su rival (serializable en caso de que lo haya olvidado), es parte del SDK de Android. Ahora, Parcelable fue diseñado específicamente de tal manera que no hay reflejo cuando se usa. Eso es porque estamos siendo realmente explícitos para el proceso de serialización.

public class TestModel implements Parcelable {


String name;

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

protected TestModel(Parcel in) {
    this.name = in.readString();


}

public String getName() {
    return name;
}

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

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

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(this.name);

}

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

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

Ahora, el ganador es

ingrese la descripción de la imagen aquí

Los resultados de las pruebas realizadas por Philippe Breault muestran que Parcelable es más de 10 veces más rápido que Serializable. Algunos otros ingenieros de Google respaldan esta declaración también.

Según ellos, el enfoque Serializable predeterminado es más lento que Parcelable. ¡Y aquí tenemos un acuerdo entre las dos partes! PERO, ¡es injusto comparar estos dos! Porque con Parcelable en realidad estamos escribiendo código personalizado. Código creado específicamente para ese POJO. Por lo tanto, no se crea basura y los resultados son mejores. Pero con el enfoque Serializable predeterminado, confiamos en el proceso de serialización automática de Java. ¡El proceso aparentemente no es personalizado en absoluto y crea mucha basura! Por lo tanto, los peores resultados.

Stop Stop !!!!, Antes de tomar una decisión

Ahora, hay otro enfoque . Todo el proceso automático detrás de Serializable se puede reemplazar por un código personalizado que utiliza los métodos writeObject () y readObject (). Estos métodos son específicos. Si queremos confiar en el enfoque serializable en combinación con un comportamiento de serialización personalizado, debemos incluir estos dos métodos con la misma firma exacta que la siguiente:

 private void writeObject(java.io.ObjectOutputStream out)
 throws IOException;

 private void readObject(java.io.ObjectInputStream in)
     throws IOException, ClassNotFoundException;

 private void readObjectNoData()
     throws ObjectStreamException;

¡Y ahora una comparación entre Parcelable y Serializable personalizado parece justo! ¡Los resultados pueden ser sorprendentes! El enfoque serializable personalizado es más de 3 veces más rápido para escrituras y 1,6 veces más rápido para lecturas que Parcelable.

Editado: -----

2) Serialización de Kotlinx

Biblioteca de serialización de Kotlinx

For Kotlin serialization need to add below dependency and plugin

implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.9.1"

apply plugin: 'kotlinx-serialization'

Su build.gradlearchivo

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlinx-serialization'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.example.smile.kotlinxretrosample"
        minSdkVersion 16
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.9.1"
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    implementation 'com.android.support:design:28.0.0'
    implementation 'com.squareup.retrofit2:retrofit:2.5.0'
    implementation 'com.squareup.okhttp3:okhttp:3.12.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

La serialización se realiza con bastante facilidad, debe anotar la clase deseada con la @Serializableanotación de la siguiente manera

import kotlinx.serialization.Serializable
@Serializable
class Field {
    var count: Int = 0
    var name: String = ""
}

Dos anotaciones más para tener en cuenta son transienty optional. El uso de transitorios hará que el serializador ignore ese campo y el uso opcional permitirá que el serializador no se rompa si falta un campo, pero al mismo tiempo será necesario proporcionar un valor predeterminado.

@Optional
var isOptional: Boolean = false
@Transient
var isTransient: Boolean = false

Nota : Esto también puede funcionar con clases de datos.

Ahora, para usar esto realmente en acción, tomemos un ejemplo de cómo convertir un JSON en objeto y viceversa.

 fun toObject(stringValue: String): Field {
        return JSON.parse(Field.serializer(), stringValue)
    }

    fun toJson(field: Field): String {
        //Notice we call a serializer method which is autogenerated from our class 
        //once we have added the annotation to it
        return JSON.stringify(Field.serializer(), field)
    }

Para más

Farhana
fuente
@Farhana ¿Cómo hacerlo para la clase de datos en Kotlin?
Nisarg
@Nisarg agregué Kotlin Serialization, echa un vistazo.
Farhana
@Farhana Esto fue muy perspicaz. Realmente quiero mudarme a Kotlin en el trabajo, pero los gerentes rechazan constantemente mi propuesta. Me pregunto si puedo obtener un punto de referencia para Serializable (con método personalizado) que, según usted, es 1.6 veces más rápido que Parcelable.
Abhinav Kulshreshtha
39

Si desea ser un buen ciudadano, tómese el tiempo extra para implementar Parcelable, ya que funcionará 10 veces más rápido y usará menos recursos.

Sin embargo, en la mayoría de los casos, la lentitud de Serializable no se notará. Siéntase libre de usarlo, pero recuerde que la serialización es una operación costosa, así que manténgala al mínimo.

Si está intentando pasar una lista con miles de objetos serializados, es posible que todo el proceso tarde más de un segundo. Puede hacer que las transiciones o la rotación de retrato a paisaje parezcan muy lentas.

Fuente hasta este punto: http://www.developerphil.com/parcelable-vs-serializable/

codercat
fuente
32

En Parcelable, los desarrolladores escriben código personalizado para ordenar y desarmar para que cree menos objetos basura en comparación con la serialización. El rendimiento de Parcelable sobre la serialización mejora dramáticamente (alrededor de dos veces más rápido), debido a esta implementación personalizada.

Serializable es una interfaz de marcador, lo que implica que el usuario no puede reunir los datos de acuerdo con sus requisitos. En la serialización, se realiza una operación de cálculo de referencias en una máquina virtual Java (JVM) utilizando la API de reflexión de Java. Esto ayuda a identificar el miembro y el comportamiento del objeto Java, pero también termina creando muchos objetos basura. Debido a esto, el proceso de serialización es lento en comparación con Parcelable.

Editar: ¿Cuál es el significado de ordenar y desarmar?

En pocas palabras, "cálculo de referencias" se refiere al proceso de convertir los datos o los objetos en una secuencia de bytes, y "descomposición" es el proceso inverso de convertir la secuencia de bytes a sus datos u objetos originales. La conversión se logra a través de la "serialización".

http://www.jguru.com/faq/view.jsp?EID=560072

Uts
fuente
Bastante buena explicación incluso sin un ejemplo detallado. Justo lo que necesitaba para la revisión.
sud007
20

De hecho, voy a ser el único que defiende el Serializable. La diferencia de velocidad ya no es tan drástica ya que los dispositivos son mucho mejores que hace varios años y también hay otras diferencias más sutiles. Vea mi publicación de blog sobre el tema para obtener más información.

Nemanja Kovacevic
fuente
1
Gracias por compartir. Es menos complejo de implementar serializable y la compensación debe decidirse en esos casos raros e hiperoptimización.
Ankan-Zerob 01 de
2
El punto de vista alternativo, especialmente cuando se respalda con experimentos y resultados, es muy útil. Tengo que trabajar con una gran cantidad de código fuente basado en Parcelable existente, y puedo refactorizar parte de él ahora que he leído la publicación de tu blog.
Les
14

Parcelable es una especie de estándar en el desarrollo de Android. Pero no por la velocidad

Parcelable es el enfoque recomendado para las transferencias de datos. Pero si usa serializable correctamente como se muestra en este repositorio , verá que serializable es a veces incluso más rápido que parcelable. O al menos los tiempos son comparables.

¿Parcelable es más rápido que serializable?

La serialización Java habitual en un dispositivo Android promedio (si se hace correctamente *) es aproximadamente 3.6 veces más rápida que Parcelable para escrituras y aproximadamente 1.6 veces más rápida para lecturas. También demuestra que la serialización de Java (si se hace correctamente) es un mecanismo de almacenamiento rápido que brinda resultados aceptables incluso con gráficos de objetos relativamente grandes de 11000 objetos con 10 campos cada uno.

* La nota al margen es que, por lo general, todos los que afirman ciegamente que "Parcelable es mucho más rápido" lo comparan con la serialización automática predeterminada, que utiliza mucha reflexión en su interior. Esta es una comparación injusta, porque Parcelable utiliza un procedimiento manual (y muy complicado) para escribir datos en la secuencia. Lo que generalmente no se menciona es que Java Serializable estándar de acuerdo con los documentos también se puede hacer de forma manual, utilizando los métodos writeObject () y readObject (). Para más información ver JavaDocs. Así es como debe hacerse para obtener el mejor rendimiento.

Entonces, si serializable es más rápido y fácil de implementar, ¿por qué Android tiene parcelable?

La razón es el código nativo. Parcelable se crea no solo para la comunicación entre procesos. También se puede usar para la comunicación entre códigos . Puede enviar y recibir objetos de la capa nativa de C ++. Eso es.

¿Qué deberías elegir? Ambos funcionarán bien. Pero creo que Parcelable es una mejor opción, ya que Google lo recomienda y, como puede ver en este hilo, es mucho más apreciado.

Maksim Turaev
fuente
¿Puedes ubicar tus fuentes? Yo realmente lo apreciaría. ¡¡Gracias!!
Archie G. Quiñones
2
Esa respuesta la obtuve de un desarrollador experimentado que trabaja en el proyecto relacionado con AOSP twitter.com/bwdude . Dijo que el código nativo de C ++ para la comunicación con la capa SDK usa su propia implementación de Parcelable. Supongo que habló sobre esta clase android.googlesource.com/platform/frameworks/native/+/… Sé que esta no es la mejor explicación, pero es la mejor que tengo en este momento. Si encuentra algo más, asegúrese de publicarlo aquí =)
Maksim Turaev
Ojalá pudiera votarte más de una vez. He visto a grandes expertos en Android y Java buscar la respuesta más votada aquí. La falta de documentación realmente ha impedido cualquier protagonismo para Serializable. Se siente como estos son efectos de promover una API específica. ¡Gracias!
pulp_fiction
11

1. Serializable

@ver http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html

Interfaz de qué?

  • es una interfaz Java estándar

Velocidad

  • más lento que Parcelable

2. Parcelable

@ver http://developer.android.com/reference/android/os/Parcelable.html

Interfaz de qué?

  • es la interfaz android.os
    • lo que significa que Google desarrolló Parcelable para un mejor rendimiento en Android

Velocidad

  • más rápido (porque está optimizado para su uso en el desarrollo de Android)

> En conclusión

Tenga en cuenta que Serializable es una interfaz Java estándar y Parcelable es para el desarrollo de Android

kenju
fuente
También debe agregar los usos de ellos.
Anshul Tyagi el
4

La implementación de parcelable puede ser más rápida si usa el complemento paracelable en el estudio de Android. buscar el generador de código parcelable de Android

P profundo
fuente
3

La interfaz serializable se puede usar de la misma manera que la parcelable, lo que resulta en (no mucho) mejores rendimientos. Simplemente sobrescriba esos dos métodos para manejar el proceso manual de clasificación y desensamblaje:

private void writeObject(java.io.ObjectOutputStream out)
    throws IOException
private void readObject(java.io.ObjectInputStream in)
    throws IOException, ClassNotFoundException

Aún así, me parece que al desarrollar Android nativo, usar la API de Android es el camino a seguir.

Ver :

Ceyfiroth
fuente
2

Llego tarde en la respuesta, pero publico con la esperanza de que ayudará a otros.

En términos de velocidad , Parcelable > Serializable. Pero, Custom Serializable es una excepción. Está casi en el rango de Parcelable o incluso más rápido.

Referencia: https://www.geeksforgeeks.org/customized-serialization-and-deserialization-in-java/

Ejemplo:

Clase personalizada para ser serializada

class MySerialized implements Serializable { 

    String deviceAddress = "MyAndroid-04"; 

    transient String token = "AABCDS"; // sensitive information which I do not want to serialize

    private void writeObject(ObjectOutputStream oos) throws Exception {
        oos.defaultWriteObject();
        oos.writeObject("111111" + token); // Encrypted token to be serialized
    }

    private void readObject(ObjectInputStream ois) throws Exception {
        ois.defaultReadObject(); 
        token = ((String) ois.readObject()).subString(6);  // Decrypting token
    }

}
Kushal
fuente
1

puede usar los objetos serializables en los intentos pero al momento de serializar un objeto Parcelable puede dar una excepción seria como NotSerializableException. ¿No se recomienda usar serializable con Parcelable? Por lo tanto, es mejor extender Parcelable con el objeto que desea usar con paquetes e intentos. Como este Parcelable es específico de Android, no tiene efectos secundarios. :)

Rankush Kumar
fuente
0

Serializable

Serializable es una interfaz marcable o podemos llamarla como una interfaz vacía. No tiene ningún método preinstalado. Serializable va a convertir un objeto en flujo de bytes. Por lo tanto, el usuario puede pasar los datos entre una actividad a otra actividad. La principal ventaja de serializable es que la creación y el paso de datos es muy fácil, pero es un proceso lento en comparación con parcelable.

Parcelable

El paquete capaz es más rápido que el serializable. Parcel able va a convertir objetos en flujo de bytes y pasar los datos entre dos actividades. Escribir código para paquetes es un poco complejo en comparación con la serialización. No crea más objetos temporales mientras pasa los datos entre dos actividades.

Cprk Praveen
fuente