Androidがオブジェクトをシリアル化するための2つのインターフェイスを提供するのはなぜですか? Serializableオブジェクトは、Android Binder
およびAIDLファイルと相互運用しますか?
Androidでは、アクティビティにオブジェクトを渡すことはできません。これを行うには、オブジェクトはSerializable
またはParcelable
インターフェイスを実装する必要があります。
シリアル化可能
Serializable
は標準のJavaインターフェイスです。 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");
ParcelableオブジェクトのArrayList
を次のように渡すことができます。
// 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
配列は、AndroidのIntentを介して渡すことができますSerializableは標準のJavaインターフェイスです。インターフェイスを実装することでクラスをSerializableとしてマークすると、特定の状況でJavaが自動的にクラスをシリアル化します。
Parcelableは、シリアル化を自分で実装するAndroid固有のインターフェイスです。これは、Serializableよりもはるかに効率的であり、デフォルトのJavaシリアル化スキームに関する問題を回避するために作成されました。
バインダーとAIDLはパーセル可能なオブジェクトと連携すると信じています。
ただし、IntentsでSerializableオブジェクトを使用できます。
善良な市民になりたい場合は、Parcelableの実装に余分な時間を費やしてください。Parcelableは10倍速く実行され、使用するリソースが少なくなります。
ただし、ほとんどの場合、Serializableの遅さは目立ちません。自由に使用できますが、シリアル化は高価な操作であるため、最小限に抑えてください。
数千のシリアル化されたオブジェクトのリストを渡そうとしている場合、プロセス全体が1秒以上かかる可能性があります。縦向きから横向きへのトランジションまたは回転を非常に遅く感じることがあります。
このポイントのソース: http://www.developerphil.com/parcelable-vs-serializable/
Parcelable vs vs Serializableこれら2つを参照します。
シリアル化可能、シンプルさ
Serializableとは何ですか?
Serializableは標準のJavaインターフェイスです。 Android SDKの一部ではありません。そのシンプルさがその美しさです。このインターフェースを実装するだけで、POJOはあるアクティビティから別のアクティビティにジャンプする準備ができます。
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は別のインターフェイスです。ライバル(忘れた場合にシリアル化可能)にもかかわらず、それは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つの当事者の間で合意があります!しかし、これら2つをまったく比較するのは不公平です! Parcelableでは実際にカスタムコードを記述しているためです。その1つのPOJO用に特別に作成されたコード。したがって、ガベージは作成されず、結果は良くなります。しかし、デフォルトのSerializableアプローチでは、Javaの自動シリアル化プロセスに依存しています。プロセスは明らかにまったくカスタムではなく、大量のゴミを作成します!したがって、悪い結果になります。
Stop Stop !!!!、決定する前に
今、別のアプローチがあります。 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倍高速です。
Parcelableでは、開発者は、マーシャリングとアンマーシャリングのカスタムコードを記述するため、シリアル化に比べてガベージオブジェクトが少なくなります。このカスタム実装により、Parcelable over Serializationのパフォーマンスは劇的に向上します(約2倍高速)。
シリアル化はマーカーインターフェイスです。これは、ユーザーが要件に従ってデータをマーシャリングできないことを意味します。シリアライゼーションでは、JavaリフレクションAPIを使用して、Java仮想マシン(JVM)でマーシャリング操作が実行されます。これは、Javaオブジェクトのメンバーと動作を識別するのに役立ちますが、多くのガベージオブジェクトを作成することにもなります。 このため、SerializationプロセスはParcelableと比較して低速です。
編集:マーシャリングとアンマーシャリングの意味は何ですか?
簡単に言うと、「マーシャリング」とは、データまたはオブジェクトをバイトストリームに変換するプロセスを指し、「アンマーシャリング」とは、バイトストリームベックを元のデータまたはオブジェクトに変換する逆のプロセスです。変換は「シリアル化」によって実現されます。
私は実際にSerializableを提唱する1人の男になります。デバイスは数年前よりもはるかに優れており、他にも微妙な違いがあるため、速度の違いはそれほど劇的ではありません。詳細については、 私のブログ 問題に関する投稿を参照してください。
@see 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
Android studioでparacelableプラグインを使用すると、parcelableの実装が速くなる可能性があります。 Android Parcelable Code Generatorを検索します
データ転送には、小包が推奨されるアプローチです。しかし、 this repo に示されているようにserializableを正しく使用すると、serializableがパーセル可能よりもさらに高速になることがあります。または、少なくともタイミングは同等です。
平均Javaデバイスでの通常のAndroidシリアル化(正しく実行された場合*)は、書き込みの場合はParcelableの約3.6倍、読み取りの場合は約1.6倍高速です。また、Javaシリアル化(適切に行われた場合)は、それぞれ10個のフィールドを持つ11000個のオブジェクトの比較的大きなオブジェクトグラフでも許容可能な結果をもたらす高速ストレージメカニズムであることを証明します。
*サイドノートは、通常、「Parcelableの方が速い」と盲目的に述べるすべての人が、内部で多くのリフレクションを使用するデフォルトの自動シリアル化と比較していることです。 Parcelableはストリームにデータを書き込む手動の(そして非常に複雑な)手順を使用するため、これは不公平な比較です。通常、言及されていないのは、ドキュメントに従って標準のJava SerializableをwriteObject()およびreadObject()メソッドを使用して手動で行うこともできるということです。詳細については、JavaDocsを参照してください。これは、最高のパフォーマンスを得るための方法です。
理由はネイティブコードです。 Parcelableは、プロセス間通信だけでなく作成されます。 インターコード通信にも使用できます。 C++ネイティブレイヤーからオブジェクトを送信および受信できます。それでおしまい。
何を選ぶべきですか?両方ともうまくいきます。しかし、Parcelableはgoogleによって推奨されており、このスレッドからわかるように、Parcelableがより良い選択だと思います。
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オブジェクトをシリアル化するときに、NotSerializableExceptionなどの重大な例外が発生する可能性があります。 Parcelableでserializableを使用することは推奨されませんか?したがって、バンドルおよびインテントで使用するオブジェクトでParcelableを拡張することをお勧めします。このParcelableはAndroid固有であるため、副作用はありません。 :)
シリアル化はリフレクションを使用し、多くのGCを引き起こすため、Binderでシリアル化できるよりもはるかに高速にパーセル可能です。 Parcelableは、オブジェクトを渡すために最適化する設計です。
参照へのリンクはこちらです。 http://www.developerphil.com/parcelable-vs-serializable/