カスタムオブジェクトをParcelableにするにはどうすればよいですか?


338

オブジェクトをParcelableにしようとしています。ただし、私にはカスタムオブジェクトがあり、それらのオブジェクトにはArrayList、他のカスタムオブジェクトの属性があります。

これを行う最善の方法は何でしょうか?

回答:


431

この例は、ここここ(コードはここにあります)ここにあります

このためのPOJOクラスを作成できますが、それを行うためにいくつかの追加コードを追加する必要がありますParcelable。実装を見てください。

public class Student implements Parcelable{
        private String id;
        private String name;
        private String grade;

        // Constructor
        public Student(String id, String name, String grade){
            this.id = id;
            this.name = name;
            this.grade = grade;
       }
       // Getter and setter methods
       .........
       .........

       // Parcelling part
       public Student(Parcel in){
           String[] data = new String[3];

           in.readStringArray(data);
           // the order needs to be the same as in writeToParcel() method
           this.id = data[0];
           this.name = data[1];
           this.grade = data[2];
       }

       verride
       public int describeContents(){
           return 0;
       }

       @Override
       public void writeToParcel(Parcel dest, int flags) {
           dest.writeStringArray(new String[] {this.id,
                                               this.name,
                                               this.grade});
       }
       public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
           public Student createFromParcel(Parcel in) {
               return new Student(in); 
           }

           public Student[] newArray(int size) {
               return new Student[size];
           }
       };
   }

このクラスを作成すると、このクラスのオブジェクトをこのように簡単に渡しIntentて、ターゲットアクティビティでこのオブジェクトを回復できます。

intent.putExtra("student", new Student("1","Mike","6"));

ここで、学生は、バンドルからデータを展開するために必要なキーです。

Bundle data = getIntent().getExtras();
Student student = (Student) data.getParcelable("student");

この例では、Stringタイプのみを示しています。ただし、必要なあらゆる種類のデータを分割できます。やってみて。

編集:Rukmal Diasによって提案された別の


@Rukmal Dias 10x。実際、これらのリンクは将来いつかアクティブでなくなるため、回答を編集してコードを追加する必要があります。
フィクション

16
通常の文字列ではなくカスタムオブジェクトを渡す方法を尋ねるOP。誰でも通常の文字列を渡すことができます。カスタムオブジェクトで作成する方法を説明してください

LocalBroadcastManagerを使用して送信するだけの場合、エンコード/デコード部分を実際に実装する必要がありますか?Parcelableを実装して追加として配置するだけで十分ですか?
JohnyTex

文字列を連続して書き込むのではなく、なぜ文字列配列を使用するのですか?
クエンティンロイ

writeToParcelメソッド内で文字列配列を作成する際のメンバーの順序は重要ですか?
Prakhar Mohan Srivastava 2017


113

IntelliJ IDEAとAndroid Studioには、このためのプラグインがあります。

これらのプラグインは、クラスのフィールドに基づいてAndroid Parcelableボイラープレートコードを生成します。

プラグインのデモ


そんなことをするための新しい方法、TIL
sud007 2016

56

1.インポート Android Parcelable code generator

ここに画像の説明を入力してください

2.クラスを作成する

public class Sample {
    int id;
    String name;
}

3.生成>メニューからParcelable

ここに画像の説明を入力してください ここに画像の説明を入力してください

できました。


7
[リポジトリの参照]ダイアログの場所がわからない場合:ボタンFile > Settings... > PluginsをクリックしBrowse repositories...ます。
DaedalusAlpha 2016年

ありがとう、たくさん助けてくれました!
Strahinja Ajvaz 2016年

21

どうやって?注釈付き。

POJOに特別な注釈を付けるだけで、あとはライブラリが行います。

警告!

Hrisey、Lombok、およびその他のコード生成ライブラリがAndroidの新しいビルドシステムと互換性があるかどうかはわかりません。ホットスワップコード(jRebel、Instant Runなど)でうまく機能する場合と機能しない場合があります。

長所:

  • コード生成ライブラリは、ボイラープレートソースコードからあなたを救います。
  • アノテーションはクラスを美しくします。

短所:

  • 単純なクラスに適しています。複雑なクラスをパーセル可能にするのは難しいかもしれません。
  • LombokとAspectJは一緒にプレイするとうまくいきません。【詳細】
  • 警告をご覧ください。

Hrisey

警告!

HriseyにはJava 8に関する既知の問題があるため、現在はAndroid開発に使用できません。#1シンボルエラーが見つからない(JDK 8)を参照してください。

HriseyはLombokに基づいています。使用ParcelableクラスHriseyを

@hrisey.Parcelable
public final class POJOClass implements android.os.Parcelable {
    /* Fields, accessors, default constructor */
}

これで、Parcelableインターフェースのメソッドを実装する必要はありません。Hriseyは、前処理フェーズ中に必要なすべてのコードを生成します。

Gradle依存関係のHrisey:

provided "pl.mg6.hrisey:hrisey:${hrisey.version}"

サポートさているタイプについては、こちらご覧ください。そのArrayList中にあります。

IDE用のプラグイン-Hrisey xor Lombok *-をインストールして、その素晴らしい機能の使用を開始してください!

ここに画像の説明を入力してください
* HriseyプラグインとLombokプラグインを一緒に有効にしないでください。有効にすると、IDEの起動中にエラーが発生します。


小包

使用ParcelableクラスParcelerを

@java.org.parceler.Parcel
public class POJOClass {
    /* Fields, accessors, default constructor */
}

生成されたコードを使用するには、生成されたクラスを直接参照するか、Parcelsユーティリティクラスを使用して

public static <T> Parcelable wrap(T input);

を逆参照するには@ParcelParcelsクラスの次のメソッドを呼び出すだけです

public static <T> T unwrap(Parcelable input);

Gradle依存関係のパーセル:

compile "org.parceler:parceler-api:${parceler.version}"
provided "org.parceler:parceler:${parceler.version}"

サポートされている属性タイプについては、READMEを参照してください。


AutoParcel

AutoParcelは、Parcelable値の生成を可能にするAutoValue拡張です。

注釈付きモデルに追加implements Parcelableするだけ@AutoValueです:

@AutoValue
abstract class POJOClass implements Parcelable {
    /* Note that the class is abstract */
    /* Abstract fields, abstract accessors */

    static POJOClass create(/*abstract fields*/) {
        return new AutoValue_POJOClass(/*abstract fields*/);
    }
}

GradleビルドファイルのAutoParcel:

apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'

repositories {
    /*...*/
    maven {url "https://clojars.org/repo/"}
}

dependencies {
    apt "frankiesardo:auto-parcel:${autoparcel.version}"
}

PaperParcel

PaperParcelは、KotlinとJava用のタイプセーフなParcelableボイラープレートコードを自動的に生成する注釈プロセッサです。PaperParcelは、Kotlinデータクラス、AutoValue拡張機能を介したGoogleのAutoValue、または通常のJava Beanオブジェクトのみをサポートしています。

docsからの使用例。
でデータクラスに注釈を付け@PaperParcel、実装しPaperParcelable、次のようなJVM静的インスタンスを追加しますPaperParcelable.Creator

@PaperParcel
public final class Example extends PaperParcelable {
    public static final PaperParcelable.Creator<Example> CREATOR = new PaperParcelable.Creator<>(Example.class);

    private final int test;

    public Example(int test) {
        this.test = test;
    }

    public int getTest() {
        return test;
    }
}

Kotlinユーザーの場合は、Kotlinの使用法を参照してください。AutoValueユーザーの場合は、AutoValueの使用法を参照してください。


ParcelableGenerator

ParcelableGenerator (READMEは中国語で書かれているので理解できません。英語-中国語を話す開発者からのこの回答への貢献は大歓迎です)

READMEの使用例。

import com.baoyz.pg.Parcelable;

@Parcelable
public class User {

    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

}

アンドロイド-APTのAndroidメーカーとの組み合わせでの注釈プロセッサでの作業中にプラグインを補助します。


7

Parcelableクラスを作成する最も簡単な方法を見つけました

ここに画像の説明を入力してください


1
小さなデータではうまく機能しますが、複雑なデータを取得しても機能しません
Manohar Reddy

1

非常に簡単です。Androidスタジオのプラグインを使用して、オブジェクトをParcelableにすることができます。

public class Persona implements Parcelable {
String nombre;
int edad;
Date fechaNacimiento;

public Persona(String nombre, int edad, Date fechaNacimiento) {
    this.nombre = nombre;
    this.edad = edad;
    this.fechaNacimiento = fechaNacimiento;
}

@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(this.nombre);
    dest.writeInt(this.edad);
    dest.writeLong(fechaNacimiento != null ? fechaNacimiento.getTime() : -1);
}

protected Persona(Parcel in) {
    this.nombre = in.readString();
    this.edad = in.readInt();
    long tmpFechaNacimiento = in.readLong();
    this.fechaNacimiento = tmpFechaNacimiento == -1 ? null : new Date(tmpFechaNacimiento);
}

public static final Parcelable.Creator<Persona> CREATOR = new Parcelable.Creator<Persona>() {
    public Persona createFromParcel(Parcel source) {
        return new Persona(source);
    }

    public Persona[] newArray(int size) {
        return new Persona[size];
    }
};}

4
どういうプラグインですか?
naXa

0

これで、Parcelerライブラリを使用して、カスタムクラスをparcelableに変換できます。@Parcelで POJOクラスに注釈を付けるだけです。例えば

    @Parcel
    public class Example {
    String name;
    int id;

    public Example() {}

    public Example(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getName() { return name; }

    public int getId() { return id; }
}

Exampleクラスのオブジェクトを作成してParcelsをラップし、インテントを介してバンドルとして送信できます。例えば

Bundle bundle = new Bundle();
bundle.putParcelable("example", Parcels.wrap(example));

カスタムクラスオブジェクトを取得するには、次を使用します

Example example = Parcels.unwrap(getIntent().getParcelableExtra("example"));

0

Android parcableにはいくつかのユニークな点があります。それらは以下のとおりです。

  1. パーセルは、パーセルにデータを配置するのと同じ順序で読み取る必要があります。
  2. 小包から読み取った後、小包は空になります。これは、小包に3つのデータがある場合です。その後、3回読み取った後、小包は空になります。

例:クラスをParcebleにするには、Parcebleを実装する必要があります。Percableには2つの方法があります:

int describeContents();
void writeToParcel(Parcel var1, int var2);

Personクラスがあり、firstName、lastName、およびageの3つのフィールドがあるとします。Parcebleインターフェースを実装した後。このインターフェースは以下のとおりです。

import android.os.Parcel;
import android.os.Parcelable;
public class Person implements Parcelable{
    private String firstName;
    private String lastName;
    private int age;

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeString(firstName);
        parcel.writeString(lastName);
        parcel.writeInt(age);
    }

}

ここwriteToParcelでは、パーセルにデータを順番に書き込んだり追加したりする方法を示します。この後、パーセルからデータを読み取るための次のコードを追加する必要があります。

protected Person(Parcel in) {
        firstName = in.readString();
        lastName = in.readString();
        age = in.readInt();
    }

    public static final Creator<Person> CREATOR = new Creator<Person>() {
        @Override
        public Person createFromParcel(Parcel in) {
            return new Person(in);
        }

        @Override
        public Person[] newArray(int size) {
            return new Person[size];
        }
    };

ここでは、Personクラスが小包を取り、書き込み中に同じ順序でデータを取得しています。

これで、意図getExtraputExtraコードの間に以下が与えられます:

追加で入れます:

Person person=new Person();
                person.setFirstName("First");
                person.setLastName("Name");
                person.setAge(30);

                Intent intent = new Intent(getApplicationContext(), SECOND_ACTIVITY.class);
                intent.putExtra()
                startActivity(intent); 

追加で入手:

Person person=getIntent().getParcelableExtra("person");

フルパーソンクラスは以下の通りです:

import android.os.Parcel;
import android.os.Parcelable;

public class Person implements Parcelable{
    private String firstName;
    private String lastName;
    private int age;



    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeString(firstName);
        parcel.writeString(lastName);
        parcel.writeInt(age);
    }

    protected Person(Parcel in) {
        firstName = in.readString();
        lastName = in.readString();
        age = in.readInt();
    }

    public static final Creator<Person> CREATOR = new Creator<Person>() {
        @Override
        public Person createFromParcel(Parcel in) {
            return new Person(in);
        }

        @Override
        public Person[] newArray(int size) {
            return new Person[size];
        }
    };

}

Hope this will help you 
Thanks :)

0

Android StudioでプラグインなしでParcelableクラスを作成する

クラスにParcelableを実装し、「implements Parcelable」にカーソルを合わせて、ヒット Alt+Enterして選択しますAdd Parcelable implementation(画像を参照)。それでおしまい。

ここに画像の説明を入力してください


-3

置く: bundle.putSerializable("key",(Serializable) object);

取得するため: List<Object> obj = (List<Object>)((Serializable)bundle.getSerializable("key"));


3
これはClassCastException、オブジェクトがを実装しない場合につながりますSerializable
naXa 2014

1
このコードスニペットは問題を解決する可能性がありますが、説明を含めると、投稿の質を高めるのに役立ちます。あなたは将来の読者のための質問に答えていることを覚えておいてください、そしてそれらの人々はあなたのコード提案の理由を知らないかもしれません。また、コードと説明コメントを混同しないようにしてください。これにより、コードと説明の両方が読みにくくなります。
Ashish Ahuja 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.