Warum bietet Android zwei Schnittstellen zum Serialisieren von Objekten? Interoperabelisierbare Objekte mit Android- Binder
und AIDL-Dateien?
Warum bietet Android zwei Schnittstellen zum Serialisieren von Objekten? Interoperabelisierbare Objekte mit Android- Binder
und AIDL-Dateien?
Antworten:
In Android können wir Objekte nicht einfach an Aktivitäten übergeben. Dazu müssen die Objekte entweder implementiert Serializable
oder eine Parcelable
Schnittstelle sein.
Serialisierbar
Serializable
ist eine Standard-Java-Schnittstelle. Sie können einfach die Serializable
Schnittstelle implementieren und Überschreibungsmethoden hinzufügen. Das Problem bei diesem Ansatz ist, dass Reflexion verwendet wird und es sich um einen langsamen Prozess handelt. Diese Methode erstellt viele temporäre Objekte und verursacht eine Menge Speicherbereinigung. Die Serializable
Schnittstelle ist jedoch einfacher zu implementieren.
Schauen Sie sich das folgende Beispiel an (serialisierbar):
// 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");
Paketierbar
Parcelable
Prozess ist viel schneller als Serializable
. Einer der Gründe dafür ist, dass wir den Serialisierungsprozess explizit beschreiben, anstatt ihn durch Reflexion abzuleiten. Es liegt auch nahe, dass der Code für diesen Zweck stark optimiert wurde.
Schauen Sie sich das folgende Beispiel an (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");
Sie können ArrayList
Paketobjekte wie folgt übergeben:
// 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");
Fazit
Parcelable
ist schneller als Serializable
SchnittstelleParcelable
Die Implementierung der Schnittstelle nimmt im Vergleich zur Serializable
Schnittstelle mehr Zeit in AnspruchSerializable
Schnittstelle ist einfacher zu implementieren Serializable
Die Schnittstelle erstellt viele temporäre Objekte und verursacht eine Menge SpeicherbereinigungParcelable
Array kann über Intent in Android übergeben werdenSerializable ist eine Standard-Java-Schnittstelle. Sie markieren einfach eine Klasse Serializable, indem Sie die Schnittstelle implementieren, und Java serialisiert sie in bestimmten Situationen automatisch.
Parcelable ist eine Android-spezifische Oberfläche, über die Sie die Serialisierung selbst implementieren. Es wurde entwickelt, um weitaus effizienter als Serializable zu sein und um einige Probleme mit dem Standard-Java-Serialisierungsschema zu umgehen.
Ich glaube, dass Binder und AIDL mit Paketobjekten arbeiten.
Sie können jedoch serialisierbare Objekte in Intents verwenden.
Parcelable vs Serializable Ich beziehe mich auf diese beiden.
Für Java und Kotlin
1) Java
Serialisierbar, die Einfachheit
Was ist serialisierbar?
Serializable ist eine Standard-Java-Schnittstelle. Es ist nicht Teil des Android SDK. Ihre Einfachheit ist ihre Schönheit. Durch die Implementierung dieser Schnittstelle kann Ihr POJO von einer Aktivität zur nächsten springen.
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;
}
}
Das Schöne an serialisierbar ist, dass Sie die serialisierbare Schnittstelle nur für eine Klasse und ihre untergeordneten Elemente implementieren müssen. Es handelt sich um eine Markierungsschnittstelle, dh es gibt keine zu implementierende Methode. Java wird einfach sein Bestes tun, um sie effizient zu serialisieren.
Das Problem bei diesem Ansatz ist, dass Reflexion verwendet wird und es sich um einen langsamen Prozess handelt. Dieser Mechanismus neigt auch dazu, viele temporäre Objekte zu erstellen und eine Menge Speicherbereinigung zu verursachen.
Paket, die Geschwindigkeit
Was ist Paket?
Parcelable ist eine weitere Schnittstelle. Trotz seines Rivalen (Serializable, falls Sie es vergessen haben) ist es Teil des Android SDK. Jetzt wurde Parcelable speziell so konzipiert, dass bei der Verwendung keine Reflexionen auftreten. Das liegt daran, dass wir für den Serialisierungsprozess wirklich explizit sind.
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];
}
};
}
Nun ist der Gewinner
Die Ergebnisse der von Philippe Breault durchgeführten Tests zeigen, dass Parcelable mehr als 10x schneller als Serializable ist. Einige andere Google-Ingenieure stehen ebenfalls hinter dieser Aussage.
Demnach ist der standardmäßige serielle Ansatz langsamer als Parcelable. Und hier haben wir eine Vereinbarung zwischen den beiden Parteien! ABER es ist unfair, diese beiden überhaupt zu vergleichen! Denn mit Parcelable schreiben wir tatsächlich benutzerdefinierten Code. Code, der speziell für dieses eine POJO erstellt wurde. Somit entsteht kein Müll und die Ergebnisse sind besser. Beim standardmäßigen seriellen Ansatz verlassen wir uns jedoch auf den automatischen Serialisierungsprozess von Java. Der Prozess ist anscheinend überhaupt nicht benutzerdefiniert und erzeugt viel Müll! Somit sind die Ergebnisse schlechter.
Stop Stop !!!!, bevor Sie eine Entscheidung treffen
Nun gibt es einen anderen Ansatz . Der gesamte automatische Prozess hinter Serializable kann durch benutzerdefinierten Code ersetzt werden, der die Methoden writeObject () und readObject () verwendet. Diese Methoden sind spezifisch. Wenn wir uns auf den serialisierbaren Ansatz in Kombination mit dem benutzerdefinierten Serialisierungsverhalten verlassen möchten, müssen wir diese beiden Methoden mit derselben exakten Signatur wie die folgende einschließen:
private void writeObject(java.io.ObjectOutputStream out)
throws IOException;
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
private void readObjectNoData()
throws ObjectStreamException;
Und jetzt scheint ein Vergleich zwischen Parcelable und Custom Serializable fair zu sein! Die Ergebnisse können überraschend sein! Der benutzerdefinierte serielle Ansatz ist beim Schreiben mehr als dreimal schneller und beim Lesen 1,6-mal schneller als bei Parcelable.
Bearbeitet: -----
2) Kotlinx-Serialisierung
Kotlinx Serialization Library
For Kotlin serialization need to add below dependency and plugin
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.9.1"
apply plugin: 'kotlinx-serialization'
Ihre build.gradle
Datei
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'
}
Die Serialisierung ist recht einfach. Sie müssen die beabsichtigte Klasse mit der folgenden @Serializable
Annotation versehen
import kotlinx.serialization.Serializable
@Serializable
class Field {
var count: Int = 0
var name: String = ""
}
Zwei weitere Anmerkungen sind transient
und optional
. Bei Verwendung von transient ignoriert der Serializer dieses Feld, und bei Verwendung von optional kann der Serializer nicht unterbrochen werden, wenn ein Feld fehlt. Gleichzeitig muss jedoch ein Standardwert angegeben werden.
@Optional
var isOptional: Boolean = false
@Transient
var isTransient: Boolean = false
Hinweis : Dies kann auch mit Datenklassen funktionieren.
Um dies nun tatsächlich in Aktion zu verwenden, nehmen wir ein Beispiel für die Konvertierung eines JSON in ein Objekt und zurück
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)
}
Für mehr
Serialization
.
Wenn Sie ein guter Bürger sein möchten, nehmen Sie sich die zusätzliche Zeit, um Parcelable zu implementieren, da es zehnmal schneller arbeitet und weniger Ressourcen verbraucht.
In den meisten Fällen ist die Langsamkeit von Serializable jedoch nicht erkennbar. Sie können es gerne verwenden, aber denken Sie daran, dass die Serialisierung ein teurer Vorgang ist. Halten Sie sie daher auf ein Minimum.
Wenn Sie versuchen, eine Liste mit Tausenden von serialisierten Objekten zu übergeben, dauert der gesamte Vorgang möglicherweise länger als eine Sekunde. Übergänge oder Rotationen vom Porträt zur Landschaft können sich dadurch sehr träge anfühlen.
Quelle zu diesem Punkt: http://www.developerphil.com/parcelable-vs-serializable/
In Parcelable schreiben Entwickler benutzerdefinierten Code zum Marshalling und Unmarshaling, sodass im Vergleich zur Serialisierung weniger Müllobjekte erstellt werden. Die Leistung von Parcelable over Serialization wird aufgrund dieser benutzerdefinierten Implementierung erheblich verbessert (etwa doppelt so schnell).
Serialisierbar ist eine Markierungsschnittstelle, die impliziert, dass der Benutzer die Daten nicht gemäß seinen Anforderungen zusammenstellen kann. Bei der Serialisierung wird eine Marshalling-Operation auf einer Java Virtual Machine (JVM) unter Verwendung der Java Reflection API ausgeführt. Dies hilft bei der Identifizierung des Mitglieds und des Verhaltens des Java-Objekts, führt jedoch auch dazu, dass viele Müllobjekte erstellt werden. Aus diesem Grund ist der Serialisierungsprozess im Vergleich zu Parcelable langsam.
Bearbeiten: Was bedeutet Marshalling und Unmarshalling?
In wenigen Worten bezieht sich "Marshalling" auf den Prozess des Konvertierens der Daten oder der Objekte in einen Byte-Stream, und "Unmarshalling" ist der umgekehrte Prozess des Konvertierens des Byte-Stream-Beacks in ihre ursprünglichen Daten oder Objekte. Die Konvertierung erfolgt durch "Serialisierung".
Ich werde tatsächlich derjenige sein, der sich für das Serializable einsetzt. Der Geschwindigkeitsunterschied ist nicht mehr so drastisch, da die Geräte weitaus besser sind als vor einigen Jahren und es auch andere, subtilere Unterschiede gibt. Weitere Informationen finden Sie in meinem Blogbeitrag zu diesem Thema.
Parcelable wird für die Datenübertragung empfohlen. Wenn Sie jedoch serialisierbar korrekt verwenden, wie in diesem Repo gezeigt , werden Sie feststellen, dass serialisierbar manchmal sogar schneller als paketierbar ist. Oder zumindest sind die Zeiten vergleichbar.
Die übliche Java-Serialisierung auf einem durchschnittlichen Android-Gerät (wenn richtig gemacht *) ist etwa 3,6-mal schneller als Parcelable für Schreibvorgänge und etwa 1,6-mal schneller für Lesevorgänge. Es zeigt auch, dass die Java-Serialisierung (wenn sie richtig durchgeführt wird) ein schneller Speichermechanismus ist, der selbst bei relativ großen Objektgraphen von 11000 Objekten mit jeweils 10 Feldern akzeptable Ergebnisse liefert.
* Die Nebenbemerkung ist, dass normalerweise jeder, der blind sagt, dass "Paket schneller ist", es mit der standardmäßigen automatischen Serialisierung vergleicht, bei der viel Reflexion im Inneren verwendet wird. Dies ist ein unfairer Vergleich, da Parcelable ein manuelles (und sehr kompliziertes) Verfahren zum Schreiben von Daten in den Stream verwendet. Was normalerweise nicht erwähnt wird, ist, dass Standard-Java, das gemäß den Dokumenten serialisierbar ist, auch manuell mit den Methoden writeObject () und readObject () ausgeführt werden kann. Weitere Informationen finden Sie unter JavaDocs. So sollte es gemacht werden, um die beste Leistung zu erzielen.
Der Grund ist nativer Code. Parcelable wird nicht nur für die Interprozesskommunikation erstellt. Es kann auch für die Intercode-Kommunikation verwendet werden . Sie können Objekte von der nativen C ++ - Ebene senden und empfangen. Das ist es.
Was solltest du wählen? Beides wird gut funktionieren. Aber ich denke, dass Parcelable die bessere Wahl ist, da es von Google empfohlen wird und wie Sie aus diesem Thread sehen können, viel mehr geschätzt wird.
@see http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html
@siehe http://developer.android.com/reference/android/os/Parcelable.html
Beachten Sie, dass Serializable eine Standard-Java-Oberfläche ist und Parcelable für die Android-Entwicklung vorgesehen ist
Es gibt einige Leistungsprobleme beim Marshalling und Unmarshaling. Parcelable ist doppelt so schnell wie Serializable.
Bitte gehen Sie über den folgenden Link:
http://www.3pillarglobal.com/insights/parcelable-vs-java-serialization-in-android-app-development
Die serialisierbare Schnittstelle kann auf die gleiche Weise wie die parcelable-Schnittstelle verwendet werden, was zu (nicht viel) besseren Leistungen führt. Überschreiben Sie einfach diese beiden Methoden, um den manuellen Marshalling- und Unmarshalling-Prozess zu handhaben:
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException
Dennoch scheint es mir, dass bei der Entwicklung von nativem Android die Verwendung der Android-API der richtige Weg ist.
Sehen :
Ich bin spät dran zu antworten, poste aber mit der Hoffnung, dass es anderen helfen wird.
In Bezug auf die Geschwindigkeit , Parcelable > Serializable
. Aber benutzerdefiniert serialisierbar ist Ausnahme. Es ist fast in Reichweite von Parcelable oder noch schneller.
Referenz: https://www.geeksforgeeks.org/customized-serialization-and-deserialization-in-java/
Beispiel:
Benutzerdefinierte Klasse, die serialisiert werden soll
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 viel schneller als mit Binder serialisierbar, da serialisierbar Reflexion verwenden und viele GC verursachen. Parcelable ist ein Design zur Optimierung des Objektdurchlaufs.
Hier ist ein Link zur Referenz. http://www.developerphil.com/parcelable-vs-serializable/
Sie können die serialisierbaren Objekte in den Absichten verwenden, aber zum Zeitpunkt der Serialisierung eines Parcelable-Objekts kann dies eine schwerwiegende Ausnahme wie NotSerializableException darstellen. Wird nicht empfohlen, mit Parcelable serialisierbar zu verwenden? Daher ist es besser, Parcelable um das Objekt zu erweitern, das Sie mit Bundle und Intents verwenden möchten. Da dieses Paket androidspezifisch ist, hat es keine Nebenwirkungen. :) :)
Serialisierbar
Serialisierbar ist eine markierbare Schnittstelle oder wir können sie als leere Schnittstelle aufrufen. Es sind keine Methoden vorimplementiert. Serializable konvertiert ein Objekt in einen Byte-Stream. So kann der Benutzer die Daten zwischen einer Aktivität an eine andere Aktivität übergeben. Der Hauptvorteil von serialisierbar ist, dass das Erstellen und Übergeben von Daten sehr einfach ist, aber im Vergleich zu parcelable ein langsamer Prozess ist.
Paketierbar
Paketfähig ist schneller als serialisierbar. Das Paket kann das Objekt in einen Bytestream konvertieren und die Daten zwischen zwei Aktivitäten weitergeben. Das Schreiben von paketfähigem Code ist im Vergleich zur Serialisierung etwas komplex. Es werden keine temporären Objekte mehr erstellt, während die Daten zwischen zwei Aktivitäten übertragen werden.