¿Por qué Android proporciona 2 interfaces para serializar objetos? ¿Los objetos serializables interactúan con los Binder
archivos Android y AIDL?
¿Por qué Android proporciona 2 interfaces para serializar objetos? ¿Los objetos serializables interactúan con los Binder
archivos Android y AIDL?
Respuestas:
En Android no podemos simplemente pasar objetos a actividades. Para hacer esto, los objetos deben implementarse Serializable
o Parcelable
interactuar.
Serializable
Serializable
es una interfaz estándar de Java. Simplemente puede implementar la Serializable
interfaz 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 Serializable
interfaz 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
Parcelable
El 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 ArrayList
objetos 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
Parcelable
es más rápido que la Serializable
interfazParcelable
La interfaz tarda más tiempo en implementarse en comparación con la Serializable
interfazSerializable
la interfaz es más fácil de implementar Serializable
La interfaz crea muchos objetos temporales y causa bastante recolección de basuraParcelable
matriz se puede pasar a través de Intención en AndroidSerializable 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.
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
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.gradle
archivo
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 @Serializable
anotació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 transient
y 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
Serialization
, echa un vistazo.
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/
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".
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.
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.
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.
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.
@ver http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html
@ver http://developer.android.com/reference/android/os/Parcelable.html
Tenga en cuenta que Serializable es una interfaz Java estándar y Parcelable es para el desarrollo de Android
Hay algunos problemas de rendimiento con respecto a la organización y la desorganización. Parcelable es dos veces más rápido que Serializable.
Por favor, vaya al siguiente enlace:
http://www.3pillarglobal.com/insights/parcelable-vs-java-serialization-in-android-app-development
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
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 :
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
}
}
Parcelable mucho más rápido que serializable con Binder, porque serializable usa la reflexión y causa muchos GC. Parcelable es un diseño para optimizar para pasar el objeto.
Aquí hay un enlace a la referencia. http://www.developerphil.com/parcelable-vs-serializable/
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. :)
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.