Android:ParcelableとSerializableの違いは?


313

Androidがオブジェクトをシリアル化するために2つのインターフェイスを提供するのはなぜですか?シリアライズ可能なオブジェクトは、Android BinderおよびAIDL ファイルと連動しますか?

回答:


444

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");

結論

  1. ParcelableSerializableインターフェースよりも速い
  2. Parcelable インターフェースは実装に比べて実装に時間がかかります Serializableインターフェースにます
  3. Serializable インターフェースの実装が簡単です
  4. Serializable インターフェイスは多くの一時オブジェクトを作成し、かなりのガベージコレクションを引き起こします
  5. Parcelable 配列はアンドロイドのインテントを介して渡すことができます

2
@Sujith リフレクションとはどういう意味ですか?リフレクションとは?
AnV 2016年

11
@AbhinavVutukuriリフレクションは、Object.getClass()などを使用して実行時にオブジェクト、フィールド、メソッドを検査するための用語です。
FaultException

2
データの永続化にはシリアライズ可能オブジェクトの方が適していますが、一方でパーセル化可能なオブジェクトは永続化すべきではありません。これは本当に悪い習慣です
TheAnimatrix

2
@Sujith複数の人が述べたように、Parcelableオブジェクトは(確実に)永続化できませんが、Serializableオブジェクトは(制限内で)永続化できます。あなたの答えは最高得点であり、すべての重要な違いをカバーする印象を与えるので、おそらくその点について言及する必要があります。
LarsH 2017

4
Parcelableの実装はSerializableと同じくらい高速です。AndroidStudioでParcelableを実装しているクラスでAlt + Insertを押すだけで、IDEがそれを実行します。
Ali Nem 2017年

183

Serializableは標準のJavaインターフェースです。インターフェースを実装してクラスをSerializableにマークするだけで、Javaは特定の状況でそれを自動的にシリアル化します。

小包は、シリアル化を自分で実装するAndroid固有のインターフェースです。これは、Serializableよりもはるかに効率的であり、デフォルトのJavaシリアル化スキームに関するいくつかの問題を回避するために作成されました。

バインダーとAIDLはParcelableオブジェクトで動作すると思います。

ただし、IntentsではSerializableオブジェクトを使用できます。


1
Parcelableオブジェクトをシリアル化するにはどうすればよいですか?どうすれば永続化できますか?
Hades

@Hadedオブジェクトの状態の内容を取得し、ファイルまたはSQLLiteデータベースに格納します。Seriliasingは、オブジェクトをAndroidの異なるコンポーネント間または異なるアプリケーション間で完全に転送可能にするのに役立ちます。
ジョナサン

6
これは素晴らしい説明です。「Parcelは汎用のシリアル化メカニズムではありません。このクラス(および任意のオブジェクトをParcelに配置するための対応するParcelable API)は、高性能IPCトランスポートとして設計されています。そのため、パーセルデータを永続ストレージに配置します。パーセル内のデータの基盤となる実装を変更すると、古いデータが読み取れなくなる可能性があります。」developer.android.com/reference/android/os/Parcel.html
Sam003

@Zhisheng任意のオブジェクトとはどういう意味ですか?小包に入れることができるオブジェクトの種類は?
hasnain_ahmad 2015年

オブジェクトをgsonではなくjson文字列に変換するのはどうですか?
FOO

57

パーセル可能 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)
    }

以下のためのより多くの


@Farhana Kotlinのデータクラスでそれを行う方法
Nisarg、

@Nisarg私はコトリンを追加しましSerializationた、見てください。
Farhana、

@Farhanaこれはとても洞察に満ちていました。私は仕事でコトリンに移りたいと思っていますが、私の提案はマネージャーによって絶えず拒否されています。Parcelableの1.6倍の高速化が可能なSerializable(カスタムメソッドを使用)のベンチマークを取得できるかどうか疑問に思っています。
Abhinav Kulshreshtha

39

良き市民になりたい場合は、Parcelableを10倍速く実行し、使用するリソースを少なくするため、余分な時間をかけて実装してください。

ただし、ほとんどの場合、Serializableの速度低下は顕著ではありません。自由に使用してください。ただし、シリアル化は負荷の高い操作であるため、最小限に抑えるようにしてください。

何千ものシリアル化されたオブジェクトを含むリストを渡そうとしている場合、プロセス全体が1秒以上かかる可能性があります。縦長から横長への移行や回転を非常に鈍く感じます。

この時点までのソース:http : //www.developerphil.com/parcelable-vs-serializable/


32

Parcelableでは、開発者はマーシャリングとアンマーシャリング用のカスタムコードを記述して、シリアライゼーションと比較して作成されるガベージオブジェクトを減らします。このカスタム実装により、Parcelable over Serializationのパフォーマンスが劇的に向上します(約2倍速くなります)。

Serializableはマーカーインターフェイスであり、ユーザーが要件に応じてデータをマーシャリングできないことを意味します。シリアライゼーションでは、JavaリフレクションAPIを使用して、Java仮想マシン(JVM)でマーシャリング操作が実行されます。これは、Javaオブジェクトのメンバーと動作を識別するのに役立ちますが、多くのガベージオブジェクトを作成することにもなります。このため、SerializationプロセスはParcelableに比べて遅くなります。

編集: マーシャリングとアンマーシャリングの意味は何ですか?

つまり、「マーシャリング」はデータまたはオブジェクトをバイトストリームに変換するプロセスを指し、「アンマーシャリング」はバイトストリームbeackを元のデータまたはオブジェクトに変換する逆のプロセスを指します。変換は「シリアル化」によって実現されます。

http://www.jguru.com/faq/view.jsp?EID=560072


冗長な例がなくてもかなり良い説明。修正に必要なものだけ。
sud007

20

私は実際、Serializableを擁護する一人の人物になります。デバイスは数年前よりもはるかに優れており、他にも微妙な違いがあるため、速度の違いはそれほど急激ではありません。詳細について、問題に関する私のブログ投稿を参照しください。


1
シェアしていただきありがとうございます。シリアライズ可能を実装するのはそれほど複雑ではありません。トレードオフは、これらのまれなハイパー最適化のケースで決定する必要があります。
アンカンゼロブ2015

2
代替の視点は、特に実験と結果に裏打ちされている場合、非常に役立ちます。多くの既存のParcelableベースのソースコードを使用する必要があり、ブログの投稿を読んだので、その一部をリファクタリングする場合があります。
Les

14

Parcelableは、Android開発における一種の標準です。しかし、速度のためではありません

Parcelableは、データ転送の推奨アプローチです。しかし、このリポジトリに示されているようにシリアライズ可能性を正しく使用すると、シリアライズ可能性がパーセル可能性よりもさらに高速になる場合があります。または、少なくともタイミングは同等です。

ParcelableはSerializableより高速ですか?

平均的なAndroidデバイスでの通常のJavaシリアライゼーション(正しく行われた場合*)は、書き込みの場合はParcelableの約3.6倍、読み取りの場合は約1.6倍高速です。また、Javaシリアライゼーション(正しく実行された場合)が高速ストレージメカニズムであることを証明します。これは、10個のフィールドを持つ11000オブジェクトの比較的大きなオブジェクトグラフでも許容できる結果を提供します。

*傍注は、通常、「Parcelableは非常に高速である」と盲目的に述べるすべての人が、内部で多くのリフレクションを使用するデフォルトの自動シリアル化と比較するということです。Parcelableはデータをストリームに書き込むための手動の(そして非常に複雑な)手順を使用するため、これは不公平な比較です。通常言及されていないのは、ドキュメントに従って標準のJava Serializableを、writeObject()メソッドとreadObject()メソッドを使用して手動で行うこともできるということです。詳細については、JavaDocsを参照してください。これは、最高のパフォーマンスを得るために行う方法です。

それで、シリアライズ可能の方が実装が高速で簡単な場合、なぜAndroidはまったくパーセル可能であるのでしょうか。

理由はネイティブコードです。Parcelableは、プロセス間通信だけでなく作成されます。コード間通信にも使用できます。C ++ネイティブレイヤーからオブジェクトを送信および受信できます。それでおしまい。

あなたは何を選ぶべきですか?どちらもうまくいきます。しかし、Googleが推奨しているため、Parcelableの方が適していると思います。このスレッドからわかるように、はるかに高く評価されています。


情報源を特定できますか?とても感謝しております。ありがとう!!
Archie G.Quiñones19年

2
その答えは、AOSP関連プロジェクトtwitter.com/bwdudeに取り組んでいる経験豊富な開発者から得たものです。彼は、SDKレイヤーとの通信用のネイティブC ++コードは、Parcelableの独自の実装を使用すると述べました。私は彼がこのクラスの話を推測android.googlesource.com/platform/frameworks/native/+/... 私は、これが最良の説明ではないことを知っているが、それは私が今持っている最高です。何か他のものを見つける場合は、必ずここに投稿してください=)
Maksim Turaev

私があなたに複数回賛成できることを望みます。ここでは、AndroidとJavaの優れたエキスパートが最も賛成の答えを求めているところを見てきました。ドキュメントが不足しているため、Serializableの脚光はまったくありません。このような感じは、特定のAPIを宣伝する効果です。ありがとう!
pulp_fiction

11

1.シリアライズ可能

@http ://docs.oracle.com/javase/7/docs/api/java/io/Serializable.htmlを参照

何のインターフェース?

  • 標準のJavaインターフェースです

速度

  • Parcelableより遅い

2.小​​包

@see http://developer.android.com/reference/android/os/Parcelable.html

何のインターフェース?

  • android.osインターフェースです
    • これは、GoogleがParcelableを開発してAndroidのパフォーマンスを向上させたことを意味します

速度

  • より高速(Android開発での使用に最適化されているため)

>結論として

Serializableは標準のJavaインターフェースであり、ParcelableはAndroid開発用であることに注意してください。


それらの用途も追加する必要があります。
Anshul Tyagi


4

Androidスタジオでparacelableプラグインを使用すると、parcelableの実装が速くなります。Android Parcelableコードジェネレーターを検索する


3

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を使用するのがよいようです。

見る :


2

回答は遅れますが、他の人の役に立つことを期待して投稿します。

スピードに関しては、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
    }

}


1

インテントでシリアル化可能なオブジェクトを使用できますが、Parcelableオブジェクトをシリアル化するときに、NotSerializableExceptionなどの重大な例外が発生する可能性があります。Parcelableでserializableを使用することはお勧めしませんか?したがって、バンドルとインテントで使用するオブジェクトでParcelableを拡張することをお勧めします。このParcelableはandroid固有なので、副作用はありません。:)


0

シリアライズ可能

Serializableはマーク可能なインターフェイスであるか、空のインターフェイスとして呼び出すことができます。事前に実装されたメソッドはありません。Serializableはオブジェクトをバイトストリームに変換します。したがって、ユーザーは1つのアクティビティーから別のアクティビティーにデータを渡すことができます。シリアライズ可能の主な利点は、データの作成と受け渡しが非常に簡単なことですが、parcelableに比べると処理が遅くなります。

小包

小包はシリアル化可能よりも高速です。Parcelableはオブジェクトをバイトストリームに変換し、2つのアクティビティ間でデータを渡します。パーセル可能なコードの記述は、シリアライゼーションと比較すると少し複雑です。2つのアクティビティ間でデータを受け渡すときに、一時オブジェクトがさらに作成されることはありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.