Androidがオブジェクトをシリアル化するために2つのインターフェイスを提供するのはなぜですか?シリアライズ可能なオブジェクトは、Android Binder
およびAIDL ファイルと連動しますか?
Androidがオブジェクトをシリアル化するために2つのインターフェイスを提供するのはなぜですか?シリアライズ可能なオブジェクトは、Android Binder
およびAIDL ファイルと連動しますか?
回答:
Androidでは、オブジェクトをアクティビティに単に渡すことはできません。これを行うには、オブジェクトを実装Serializable
またはParcelable
インターフェイスする必要があります。
シリアライズ可能
Serializable
標準のJavaインターフェースです。Serializable
インターフェースを実装し、オーバーライドメソッドを追加するだけです。このアプローチの問題は、リフレクションが使用され、処理が遅いことです。このメソッドは、多くの一時オブジェクトを作成し、かなりのガベージコレクションを引き起こします。ただし、Serializable
インターフェースの実装は簡単です。
以下の例を見てください(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
プロセスはSerializable
。よりはるかに高速です。この理由の1つは、リフレクションを使用して推論するのではなく、シリアル化プロセスについて明示していることです。また、この目的のためにコードが大幅に最適化されているのも当然です。
以下の例(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");
ArrayList
次のようにParcelableオブジェクトを渡すことができます。
// 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");
結論
Parcelable
Serializable
インターフェースよりも速いParcelable
インターフェースは実装に比べて実装に時間がかかります Serializable
インターフェースにますSerializable
インターフェースの実装が簡単です Serializable
インターフェイスは多くの一時オブジェクトを作成し、かなりのガベージコレクションを引き起こしますParcelable
配列はアンドロイドのインテントを介して渡すことができますSerializableは標準のJavaインターフェースです。インターフェースを実装してクラスをSerializableにマークするだけで、Javaは特定の状況でそれを自動的にシリアル化します。
小包は、シリアル化を自分で実装するAndroid固有のインターフェースです。これは、Serializableよりもはるかに効率的であり、デフォルトのJavaシリアル化スキームに関するいくつかの問題を回避するために作成されました。
バインダーとAIDLはParcelableオブジェクトで動作すると思います。
ただし、IntentsではSerializableオブジェクトを使用できます。
パーセル可能 vs シリアライズ可能私はこれら2つを参照します。
JavaおよびKotlinの場合
1)Java
シリアライズ可能、シンプル
シリアライズ可能とは何ですか?
Serializableは標準のJavaインターフェースです。Android SDKの一部ではありません。そのシンプルさはその美しさです。このインターフェースを実装するだけで、POJOは1つのアクティビティから別のアクティビティにジャンプする準備ができます。
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;
}
}
Serializableの優れている点は、クラスとその子にSerializableインターフェースを実装するだけでよいということです。これはマーカーインターフェイスです。つまり、実装するメソッドはありません。Javaは効率的にシリアル化するために最善を尽くします。
このアプローチの問題は、リフレクションが使用され、処理が遅いことです。このメカニズムは、多くの一時オブジェクトを作成し、かなりのガベージコレクションを引き起こす傾向もあります。
Parcelable、The Speed
Parcelableとは何ですか?
Parcelableは別のインターフェースです。そのライバル(忘れた場合に備えてシリアライズ可能)にも関わらず、Android SDKの一部です。現在、Parcelableは、使用時に反射がないように特別に設計されています。これは、シリアル化プロセスを明確に示しているためです。
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];
}
};
}
今、勝者は
Philippe Breaultが実施したテストの結果は、ParcelableがSerializableよりも10倍以上速いことを示しています。他のGoogleエンジニアもこの声明を支持しています。
彼らによれば、デフォルトのSerializableアプローチはParcelableよりも低速です。そして、ここで私たちは両者の間に合意があります!しかし、これら2つをまったく比較するのは不公平です!Parcelableでは実際にカスタムコードを作成しているからです。その1つのPOJO用に特別に作成されたコード。したがって、ガベージは作成されず、結果はより良くなります。しかし、デフォルトのSerializableアプローチでは、Javaの自動シリアル化プロセスに依存しています。プロセスは明らかにカスタム化されておらず、大量のゴミを作成します。したがって、悪い結果になります。
ストップストップ!!!!、決定する前に
今、別のアプローチがあります。Serializableの背後にある自動プロセス全体を、writeObject()およびreadObject()メソッドを使用するカスタムコードで置き換えることができます。これらの方法は固有です。カスタムのシリアル化動作と組み合わせてSerializableアプローチに依存したい場合は、以下のメソッドとまったく同じシグネチャを持つこれら2つのメソッドを含める必要があります。
private void writeObject(java.io.ObjectOutputStream out)
throws IOException;
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
private void readObjectNoData()
throws ObjectStreamException;
そして今、ParcelableとカスタムSerializableの比較は公平に思えます!結果は意外かもしれません!カスタムのSerializableアプローチは、Parcelableに比べて、書き込みの3倍以上、読み取りの1.6倍以上高速です。
編集:-----
2)Kotlinxシリアル化
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'
あなたのbuild.gradle
ファイル
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'
}
シリアライズは非常に簡単に行わ@Serializable
れます。以下のように、目的のクラスに注釈を付ける必要があります
import kotlinx.serialization.Serializable
@Serializable
class Field {
var count: Int = 0
var name: String = ""
}
注意すべき注釈がさらに2つtransient
ありoptional
ます。トランジェントを使用すると、シリアライザはそのフィールドを無視し、オプションを使用すると、フィールドがない場合にシリアライザが中断しないようにすることができますが、同時にデフォルト値を指定する必要があります。
@Optional
var isOptional: Boolean = false
@Transient
var isTransient: Boolean = false
注:これはデータクラスでも機能します。
これを実際に使用するために、JSONをオブジェクトに変換して戻す方法の例を見てみましょう
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)
}
以下のためのより多くの
Serialization
た、見てください。
良き市民になりたい場合は、Parcelableを10倍速く実行し、使用するリソースを少なくするため、余分な時間をかけて実装してください。
ただし、ほとんどの場合、Serializableの速度低下は顕著ではありません。自由に使用してください。ただし、シリアル化は負荷の高い操作であるため、最小限に抑えるようにしてください。
何千ものシリアル化されたオブジェクトを含むリストを渡そうとしている場合、プロセス全体が1秒以上かかる可能性があります。縦長から横長への移行や回転を非常に鈍く感じます。
この時点までのソース:http : //www.developerphil.com/parcelable-vs-serializable/
Parcelableでは、開発者はマーシャリングとアンマーシャリング用のカスタムコードを記述して、シリアライゼーションと比較して作成されるガベージオブジェクトを減らします。このカスタム実装により、Parcelable over Serializationのパフォーマンスが劇的に向上します(約2倍速くなります)。
Serializableはマーカーインターフェイスであり、ユーザーが要件に応じてデータをマーシャリングできないことを意味します。シリアライゼーションでは、JavaリフレクションAPIを使用して、Java仮想マシン(JVM)でマーシャリング操作が実行されます。これは、Javaオブジェクトのメンバーと動作を識別するのに役立ちますが、多くのガベージオブジェクトを作成することにもなります。このため、SerializationプロセスはParcelableに比べて遅くなります。
編集: マーシャリングとアンマーシャリングの意味は何ですか?
つまり、「マーシャリング」はデータまたはオブジェクトをバイトストリームに変換するプロセスを指し、「アンマーシャリング」はバイトストリームbeackを元のデータまたはオブジェクトに変換する逆のプロセスを指します。変換は「シリアル化」によって実現されます。
私は実際、Serializableを擁護する一人の人物になります。デバイスは数年前よりもはるかに優れており、他にも微妙な違いがあるため、速度の違いはそれほど急激ではありません。詳細については、問題に関する私のブログ投稿を参照してください。
Parcelableは、データ転送の推奨アプローチです。しかし、このリポジトリに示されているようにシリアライズ可能性を正しく使用すると、シリアライズ可能性がパーセル可能性よりもさらに高速になる場合があります。または、少なくともタイミングは同等です。
平均的なAndroidデバイスでの通常のJavaシリアライゼーション(正しく行われた場合*)は、書き込みの場合はParcelableの約3.6倍、読み取りの場合は約1.6倍高速です。また、Javaシリアライゼーション(正しく実行された場合)が高速ストレージメカニズムであることを証明します。これは、10個のフィールドを持つ11000オブジェクトの比較的大きなオブジェクトグラフでも許容できる結果を提供します。
*傍注は、通常、「Parcelableは非常に高速である」と盲目的に述べるすべての人が、内部で多くのリフレクションを使用するデフォルトの自動シリアル化と比較するということです。Parcelableはデータをストリームに書き込むための手動の(そして非常に複雑な)手順を使用するため、これは不公平な比較です。通常言及されていないのは、ドキュメントに従って標準のJava Serializableを、writeObject()メソッドとreadObject()メソッドを使用して手動で行うこともできるということです。詳細については、JavaDocsを参照してください。これは、最高のパフォーマンスを得るために行う方法です。
理由はネイティブコードです。Parcelableは、プロセス間通信だけでなく作成されます。コード間通信にも使用できます。C ++ネイティブレイヤーからオブジェクトを送信および受信できます。それでおしまい。
あなたは何を選ぶべきですか?どちらもうまくいきます。しかし、Googleが推奨しているため、Parcelableの方が適していると思います。このスレッドからわかるように、はるかに高く評価されています。
@http ://docs.oracle.com/javase/7/docs/api/java/io/Serializable.htmlを参照
@see http://developer.android.com/reference/android/os/Parcelable.html
Serializableは標準のJavaインターフェースであり、ParcelableはAndroid開発用であることに注意してください。
マーシャリングとマーシャリング解除に関して、パフォーマンスの問題がいくつかあります。ParcelableはSerializableより2倍高速です。
次のリンクにアクセスしてください。
http://www.3pillarglobal.com/insights/parcelable-vs-java-serialization-in-android-app-development
SerializableインターフェースはParcelableインターフェースと同じように使用できるため、(それほどではないが)パフォーマンスが向上します。手動のマーシャリングおよびアンマーシャリングプロセスを処理するには、これらの2つのメソッドを上書きするだけです。
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException
それでも、ネイティブのAndroidを開発するときは、Android APIを使用するのがよいようです。
見る :
回答は遅れますが、他の人の役に立つことを期待して投稿します。
スピードに関しては、Parcelable > Serializable
。ただし、Custom Serializableは例外です。これは、Parcelableの範囲内にあるか、さらに高速です。
リファレンス:https : //www.geeksforgeeks.org/customized-serialization-and-deserialization-in-java/
例:
シリアル化されるカスタムクラス
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
}
}
シリアライズ可能はリフレクションを使用し、多くのGCを引き起こすため、Binderを使用したシリアライズ可能よりもはるかに高速にパーセル可能です。Parcelableは、オブジェクトを渡すように最適化する設計です。
ここに参照へのリンクがあります。 http://www.developerphil.com/parcelable-vs-serializable/
インテントでシリアル化可能なオブジェクトを使用できますが、Parcelableオブジェクトをシリアル化するときに、NotSerializableExceptionなどの重大な例外が発生する可能性があります。Parcelableでserializableを使用することはお勧めしませんか?したがって、バンドルとインテントで使用するオブジェクトでParcelableを拡張することをお勧めします。このParcelableはandroid固有なので、副作用はありません。:)
シリアライズ可能
Serializableはマーク可能なインターフェイスであるか、空のインターフェイスとして呼び出すことができます。事前に実装されたメソッドはありません。Serializableはオブジェクトをバイトストリームに変換します。したがって、ユーザーは1つのアクティビティーから別のアクティビティーにデータを渡すことができます。シリアライズ可能の主な利点は、データの作成と受け渡しが非常に簡単なことですが、parcelableに比べると処理が遅くなります。
小包
小包はシリアル化可能よりも高速です。Parcelableはオブジェクトをバイトストリームに変換し、2つのアクティビティ間でデータを渡します。パーセル可能なコードの記述は、シリアライゼーションと比較すると少し複雑です。2つのアクティビティ間でデータを受け渡すときに、一時オブジェクトがさらに作成されることはありません。