18

を作成しようとしていますpublic class MyClass<T extends Parcelable> implements Parcelable。の実装に困っていますParcelable。を実装するジェネリック クラスを作成することは可能Parcelableですか? (Tも実装する必要があるように、 は制限されていることに注意してくださいParcelable)。

Parcelable インターフェースには静的変数が必要であるという事実で問題が発生しています: public static final Parcelable.Creator<MyParcelable> CREATORpublic static final Parcelable.Creator<MyClass<T>> CREATORしたがって、非静的であるため、私はできませんMyParcelable<T>

アンドレ

4

4 に答える 4

23

ジェネリックを持つクラスに Parcelable を実装する際に同様の問題がありました。最初の問題は、あなたが経験していたものと同じでした:

したがって、 MyParcelable は非静的であるため、 public static final Parcelable.Creator> CREATOR を実行できません。

2 つ目は、型 erase のためClassLoaderに取得できないアクセスが必要な Parcelable オブジェクトを読み込むことでした。T

以下のクラスは、私が本番環境で使用しているクラスを適応させたもので、両方の問題を克服しています。注:このクラスを具体的にテストしていないので、問題があればお知らせください。

public class TestModel<T extends Parcelable> implements Parcelable {

private List<T> items;
private String someField;

public List<T> items() {
    return items;
}

public void setItems(List<T> newValue) {
    items = newValue;
}

public String someField() {
    return someField;
}

public void setSomeField(String newValue) {
    someField = newValue;
}

//region: Parcelable implementation

public TestModel(Parcel in) {
    someField = in.readString();

    int size = in.readInt();
    if (size == 0) {
        items = null;
    }

    else {

        Class<?> type = (Class<?>) in.readSerializable();

        items = new ArrayList<>(size);
        in.readList(items, type.getClassLoader());
    }
}

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

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(someField);

    if (items == null || items.size() == 0)
        dest.writeInt(0);

    else {
        dest.writeInt(items.size());

        final Class<?> objectsType = items.get(0).getClass();
        dest.writeSerializable(objectsType);

        dest.writeList(items);
    }
}

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

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

//endregion
}
于 2015-08-13T04:08:50.097 に答える
5

ジェネリック データ メンバー クラス名をパーセルに書き込み、クラス ローダーを作成するためにそれを読み戻します。例、

public class MyClass<T> implements Parcelable {
    T data;

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(data.getClass().getName());
        dest.writeParcelable((Parcelable) data, 0);
    }

    private MyClass(Parcel in) {
        final String className = in.readString();
        try {
            data = in.readParcelable(Class.forName(className).getClassLoader());
        } catch (ClassNotFoundException e) {
            Log.e("readParcelable", className, e);
        }
    }
于 2017-03-07T16:54:39.760 に答える
2

はい、できます。サブクラス オブジェクトの構築中にクラス名またはクラス ローダーを保存するだけで、パーセルブルの読み取り/書き込み操作中にそれを渡すことができます。

ステップバイステップの説明:

ステップ1。Generic クラスから拡張されたクラス名を次のように保存します。

public abstract class GenericClass<T> implements Parcelable {
    private String className;

ステップ 2。ジェネリック クラスから拡張されるすべてのクラスは、次のように構築中にクラス名を指定する必要があります。

public class MyClass extends GenericClass<MyClass> {

    public MyClass () {
        super();
        setClassName(MyClass.class.getName()); // Generic class setter method
    }

ステップ 3。汎用クラスでは、次のようにクラス名を getClassLoader() に読み書きできます。

public abstract class GenericClass<T> implements Parcelable {
    private String className;
    T myGenericObject;

    protected MyClass (Parcel in) {
        super(in);
        this.className = in.readString();
        ClassLoader classLoader;
        try {
            classLoader = Class.forName(this.className).getClassLoader();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        myGenericObject = in.readParcelable(classLoader);
        //... Other class members can go here
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        super.writeToParcel(dest, flags);
        dest.writeString(className);
        //... Other class members can go here
    }

}

于 2016-07-04T12:17:20.467 に答える