web-dev-qa-db-ja.com

Parcelableのサブクラスを別のParcelに書き込む

Parcelableインターフェイスを実装するクラスがあります。

class A implements Parcelable {

}

インスタンス変数としてBオブジェクトを含む別のクラスAがあります。クラスwriteToPacel内のBで、BにオブジェクトParcelを書き込みます。

class B implements Parcelable{

    public void writeToParcel(Parcel dest, int flags) {
        dest.write ??? 
    }
}

どうすればそれを読み書きできますか?

64
user4o01
class B implements Parcelable{
//lets assume you have A as a data member 

A obj;
public void writeToParcel(Parcel dest, int flags) {

        dest.writeParcelable(obj , flags);

    }
}

読みたいならこれを使って

 obj = in.readParcelable(A.class.getClassLoader());
162
confucius

反射を回避するこれを処理するより良い方法は、次のようにターゲットタイプの静的クリエーターを単に呼び出すことです。

_this.amazingObject = AmazingObject.CREATOR.createFromParcel(in);
_

this.amazingObject.writeToParcel(Parcel, int)を使用してParcelableに書き込みます

内部的に、readParcelable(ClassLoader)を呼び出すとき、これが起こります:

_public final <T extends Parcelable> T readParcelable(ClassLoader loader) {
    Parcelable.Creator<T> creator = readParcelableCreator(loader);
    if (creator == null) {
        return null;
    }
    if (creator instanceof Parcelable.ClassLoaderCreator<?>) {
        return ((Parcelable.ClassLoaderCreator<T>)creator).createFromParcel(this, loader);
    }
    return creator.createFromParcel(this);
}
_

このメソッドの最後の呼び出しは、正しいCreatorを呼び出しているだけですが、readParcelableCreatorの中には、直接呼び出すだけで回避できる多くの反射があります。

このユーティリティ呼び出しは便利です。

_import Android.os.Parcel;
import Android.os.Parcelable;

public class Parcels {

    public static void writeBoolean(Parcel dest, Boolean value) {
        dest.writeByte((byte) (value != null && value ? 1 : 0));
    }

    public static Boolean readBoolean(Parcel in){
        return in.readByte() != 0;
    }

    public static void writeParcelable(Parcel dest, int flags, Parcelable parcelable) {
        writeBoolean(dest, parcelable == null);
        if (parcelable != null) {
            parcelable.writeToParcel(dest, flags);
        }
    }

    public static <T extends Parcelable> T readParcelable(Parcel in, Parcelable.Creator<T> creator) {
        boolean isNull = readBoolean(in);
        return isNull ? null : creator.createFromParcel(in);
    }

}
_
11
pablisco

この線:

_obj = (A)in.readParcelable(A.class.getClassLoader());
_

次のように変更する必要があります。

_obj = (A)in.readParcelable(B.class.getClassLoader());
_

私は同じ問題に遭遇し、いくつかのGoogle検索を行いました、多くのWebページまたはチュートリアルでは、AにキャストしているのでA.class.getClassLoader()を使用するよう提案していますが、null値を取得するため実際には間違っています、B.class.getClassLoader() _codes are INSIDE class B_であるため。理由はわかりませんが、この方法で正しいAオブジェクトを取得できます。

コメントと検証へようこそ!!

2
Alison