Perché Android fornisce 2 interfacce per serializzare gli oggetti? Gli oggetti serializzabili interagiscono con i Binder
file Android e AIDL?
Perché Android fornisce 2 interfacce per serializzare gli oggetti? Gli oggetti serializzabili interagiscono con i Binder
file Android e AIDL?
Risposte:
In Android non possiamo semplicemente passare oggetti alle attività. Per fare ciò, gli oggetti devono implementare Serializable
o Parcelable
interfacciarsi.
Serializable
Serializable
è un'interfaccia Java standard. Puoi semplicemente implementare l' Serializable
interfaccia e aggiungere metodi di sostituzione. Il problema con questo approccio è che viene utilizzata la riflessione ed è un processo lento. Questo metodo crea molti oggetti temporanei e provoca un bel po 'di garbage collection. Però,Serializable
interfaccia è più facile da implementare.
Guarda l'esempio seguente (serializzabile):
// 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");
Impacchettabile
Parcelable
il processo è molto più veloce di Serializable
. Uno dei motivi di ciò è che siamo espliciti sul processo di serializzazione invece di usare la riflessione per inferirlo. È anche ovvio che il codice è stato fortemente ottimizzato per questo scopo.
Guarda l'esempio seguente (parcelabile):
// 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");
Puoi passare ArrayList
oggetti Parcelable come di seguito:
// 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");
Conclusione
Parcelable
è più veloce Serializable
dell'interfacciaParcelable
l'interfaccia richiede più tempo per l'implementazione rispetto Serializable
all'interfacciaSerializable
l'interfaccia è più facile da implementare Serializable
L'interfaccia crea molti oggetti temporanei e provoca un bel po 'di garbage collectionParcelable
l'array può essere passato tramite Intent in AndroidSerializable è un'interfaccia Java standard. È sufficiente contrassegnare una classe serializzabile implementando l'interfaccia e Java lo serializzerà automaticamente in determinate situazioni.
Parcelable è un'interfaccia specifica per Android in cui implementi tu stesso la serializzazione. È stato creato per essere molto più efficiente di Serializable e per aggirare alcuni problemi con lo schema di serializzazione Java predefinito.
Credo che Binder e AIDL funzionino con oggetti Parcelable.
Tuttavia, è possibile utilizzare oggetti serializzabili in Intenti.
Parcelable vs Serializable Mi riferisco a questi due.
Per Java e Kotlin
1) Java
Serializable, la semplicità
Cosa è serializzabile?
Serializable è un'interfaccia Java standard. Non fa parte dell'SDK di Android. La sua semplicità è la sua bellezza. Semplicemente implementando questa interfaccia il tuo POJO sarà pronto per passare da un'attività all'altra.
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;
}
}
Il vantaggio di serializzare è che devi solo implementare l'interfaccia Serializable su una classe e sui suoi figli. È un'interfaccia marcatore, il che significa che non esiste un metodo da implementare, Java farà semplicemente del suo meglio per serializzare in modo efficiente.
Il problema con questo approccio è che viene utilizzata la riflessione ed è un processo lento. Questo meccanismo tende anche a creare molti oggetti temporanei e causare un bel po 'di garbage collection.
Parcelable, The Speed
Cos'è Parcelable?
Parcelable è un'altra interfaccia. Nonostante il suo rivale (serializzabile nel caso in cui ti fossi dimenticato), fa parte dell'SDK di Android. Ora, Parcelable è stato specificamente progettato in modo tale da non riflettere sull'uso. Questo perché siamo veramente espliciti per il processo di serializzazione.
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];
}
};
}
Ora, il vincitore è
I risultati dei test condotti da Philippe Breault mostrano che Parcelable è più di 10 volte più veloce di Serializable. Anche alcuni altri ingegneri di Google sostengono questa affermazione.
Secondo loro, l'approccio serializzabile predefinito è più lento di Parcelable. E qui abbiamo un accordo tra le due parti! MA, non è giusto confrontare questi due! Perché con Parcelable stiamo effettivamente scrivendo codice personalizzato. Codice creato appositamente per quel POJO. Pertanto, non viene creata immondizia e i risultati sono migliori. Ma con l'approccio serializzabile predefinito, facciamo affidamento sul processo di serializzazione automatica di Java. Apparentemente il processo non è affatto personalizzato e crea molta spazzatura! Pertanto, i risultati peggiori.
Stop Stop !!!!, prima di prendere una decisione
Ora c'è un altro approccio . L'intero processo automatico dietro Serializable può essere sostituito dal codice personalizzato che utilizza i metodi writeObject () e readObject (). Questi metodi sono specifici. Se vogliamo fare affidamento sull'approccio serializzabile in combinazione con il comportamento di serializzazione personalizzato, dobbiamo includere questi due metodi con la stessa firma esatta di quello seguente:
private void writeObject(java.io.ObjectOutputStream out)
throws IOException;
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
private void readObjectNoData()
throws ObjectStreamException;
E ora un confronto tra Parcelable e Serializable personalizzato sembra giusto! I risultati potrebbero essere sorprendenti! L'approccio serializzabile personalizzato è oltre 3 volte più veloce per le scritture e 1,6 volte più veloce per le letture rispetto a Parcelable.
Modificato:-----
2) Serializzazione di Kotlinx
Kotlinx serializzazione Biblioteca
For Kotlin serialization need to add below dependency and plugin
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.9.1"
apply plugin: 'kotlinx-serialization'
Il tuo build.gradle
file
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 serializzazione viene eseguita abbastanza facilmente, è necessario annotare la classe desiderata con l' @Serializable
annotazione come di seguito
import kotlinx.serialization.Serializable
@Serializable
class Field {
var count: Int = 0
var name: String = ""
}
Altre due annotazioni da notare sono transient
e optional
. L'uso del transiente farà sì che il serializzatore ignori quel campo e l'uso di facoltativo consentirà al serializzatore di non rompersi se manca un campo, ma allo stesso tempo sarà necessario fornire un valore predefinito.
@Optional
var isOptional: Boolean = false
@Transient
var isTransient: Boolean = false
Nota : questo può funzionare anche con le classi di dati.
Ora per usarlo effettivamente in azione facciamo un esempio di come convertire un JSON in oggetto e 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)
}
Per di più
Serialization
, dai un'occhiata.
Se vuoi essere un buon cittadino, prenditi il tempo extra per implementare Parcelable dal momento che funzionerà 10 volte più velocemente e utilizzerà meno risorse.
Tuttavia, nella maggior parte dei casi, la lentezza di Serializable non sarà evidente. Sentiti libero di usarlo, ma ricorda che la serializzazione è un'operazione costosa, quindi tienila al minimo.
Se si sta tentando di passare un elenco con migliaia di oggetti serializzati, è possibile che l'intero processo richiederà più di un secondo. Può rendere molto lente le transizioni o la rotazione dal ritratto al paesaggio.
Fonte a questo punto: http://www.developerphil.com/parcelable-vs-serializable/
In Parcelable, gli sviluppatori scrivono codice personalizzato per il marshalling e il unmarshaling in modo da creare meno oggetti spazzatura rispetto alla serializzazione. Le prestazioni di Parcelable over Serialization migliorano notevolmente (circa due volte più velocemente), grazie a questa implementazione personalizzata.
Serializable è un'interfaccia marker, che implica che l'utente non può eseguire il marshalling dei dati in base alle proprie esigenze. Nella serializzazione, un'operazione di marshalling viene eseguita su una Java Virtual Machine (JVM) utilizzando l'API di riflessione Java. Questo aiuta a identificare il membro e il comportamento dell'oggetto Java, ma finisce anche per creare molti oggetti spazzatura. Per questo motivo, il processo di serializzazione è lento rispetto a Parcelable.
Modifica: Qual è il significato di marshalling e unmarshalling?
In poche parole, "marshalling" si riferisce al processo di conversione dei dati o degli oggetti in un flusso di byte e "unmarshalling" è il processo inverso di conversione del beack del flusso di byte nei loro dati o oggetti originali. La conversione avviene tramite "serializzazione".
In realtà sarò l'unico a sostenere il serializzabile. La differenza di velocità non è più così drastica poiché i dispositivi sono molto migliori rispetto a diversi anni fa e ci sono anche altre differenze più sottili. Vedi il mio post sul blog sul problema per maggiori informazioni.
Parcelable è l'approccio raccomandato per i trasferimenti di dati. Ma se si utilizza serializzabile correttamente come mostrato in questo repository , vedrai che la serializzazione a volte è anche più veloce del pacchetto. O almeno i tempi sono comparabili.
La normale serializzazione Java su un dispositivo Android medio (se eseguita correttamente *) è circa 3,6 volte più veloce di Parcelable per le scritture e circa 1,6 volte più veloce per le letture. Inoltre dimostra che la serializzazione Java (se eseguita correttamente) è un meccanismo di archiviazione veloce che fornisce risultati accettabili anche con grafici di oggetti relativamente grandi di 11000 oggetti con 10 campi ciascuno.
* Il sidenote è che di solito tutti coloro che affermano ciecamente che "Parcelable is push fast" lo confronta con la serializzazione automatica predefinita, che utilizza molta riflessione all'interno. Questo è un confronto ingiusto, perché Parcelable utilizza una procedura manuale (e molto complicata) per scrivere i dati nel flusso. Ciò che di solito non viene menzionato è che lo standard serializzabile Java secondo i documenti può anche essere fatto in modo manuale, usando i metodi writeObject () e readObject (). Per maggiori informazioni vedi JavaDocs. Ecco come dovrebbe essere fatto per le migliori prestazioni.
Il motivo è il codice nativo. Il pacchetto non viene creato solo per la comunicazione tra processi. Può anche essere usato per la comunicazione intercodale . È possibile inviare e ricevere oggetti dal livello nativo C ++. Questo è tutto.
Cosa dovresti scegliere? Entrambi funzioneranno bene. Ma penso che Parcelable sia la scelta migliore poiché è consigliato da Google e come puoi vedere da questa discussione è molto più apprezzato.
@see http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html
@see http://developer.android.com/reference/android/os/Parcelable.html
Tieni presente che Serializable è un'interfaccia Java standard e Parcelable è per lo sviluppo Android
Esistono alcuni problemi di prestazioni relativi al marshalling e al unmarshaling. Parcelable è due volte più veloce di Serializable.
Si prega di passare attraverso il seguente link:
http://www.3pillarglobal.com/insights/parcelable-vs-java-serialization-in-android-app-development
L'interfaccia serializzabile può essere utilizzata allo stesso modo di Parcelable, ottenendo prestazioni (non molto) migliori. Basta sovrascrivere questi due metodi per gestire il marshalling manuale e il processo di smarsing:
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException
Tuttavia, mi sembra che quando si sviluppa Android nativo, utilizzare l'API Android è la strada da percorrere.
Vedi:
Sono in ritardo nella risposta, ma invio con la speranza che possa aiutare gli altri.
In termini di velocità , Parcelable > Serializable
. Ma la serializzazione personalizzata è un'eccezione. È quasi nel raggio di Parcelable o anche più veloce.
Riferimento: https://www.geeksforgeeks.org/customized-serialization-and-deserialization-in-java/
Esempio :
Classe personalizzata da serializzare
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 molto più velocemente di serializzabile con Binder, perché la serializzazione utilizza la riflessione e causa molti GC. Parcelable è design per ottimizzare il passaggio dell'oggetto.
Ecco il link al riferimento. http://www.developerphil.com/parcelable-vs-serializable/
puoi usare gli oggetti serializzabili negli intenti ma al momento della serializzazione di un oggetto Parcelable può dare una grave eccezione come NotSerializableException. Non è consigliabile utilizzare serializzabile con Parcelable. Quindi è meglio estendere Parcelable con l'oggetto che si desidera utilizzare con bundle e intenti. Poiché questo Parcelable è specifico per Android, non ha effetti collaterali. :)
Serializable
Serializable è un'interfaccia contrassegnabile o possiamo chiamare come un'interfaccia vuota. Non ha metodi pre-implementati. Serializable sta per convertire un oggetto in un flusso di byte. Quindi l'utente può passare i dati tra un'attività a un'altra attività. Il vantaggio principale della serializzazione è la creazione e il passaggio dei dati è molto semplice, ma è un processo lento rispetto al pacchetto.
Impacchettabile
Il pacco è più veloce di serializzabile. Il pacchetto in grado di convertire l'oggetto in un flusso di byte e passare i dati tra due attività. La scrittura di codice pacchi è un po 'complessa rispetto alla serializzazione. Non crea più oggetti temporanei mentre passa i dati tra due attività.