9

これは一般的な Java の質問です。Androidには、インターフェースがありますParcelable

これは公式ドキュメント内の例です:

 public class MyParcelable implements Parcelable {
     private int mData;

     public int describeContents() {
         return 0;
     }

     public void writeToParcel(Parcel out, int flags) {
         out.writeInt(mData);
     }

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

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

     private MyParcelable(Parcel in) {
         mData = in.readInt();
     }
 }

と の 2 つの機能を実装する必要がdescribeContents()ありwriteToParcelます。

(問題) それ以外にも、Parcelable.Creator<T>インターフェースを CREATOR という static フィールドとして実装する必要があります。

すべてが実際には簡単です。ここで、Parcelable クラス タイプを持つジェネリック クラスを作成します。

public class ShushContainer<T extends Parcelable> implements Parcelable

Parcelable を実装できました。TwriteToParcel関数を呼び出すことができます。ただし、静的 CREATOR フィールドにアクセスできません。

public class ShushContainer<T extends Parcelable> implements Parcelable {
    Vector<T> items;
    String someField;

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(someField);
        dest.writeInt(items.size());
        for(int i=0;i<items.size();i++)
            items.get(i).writeToParcel(dest, flags);
    }

    public ShushContainer(Parcel in) {
        someField = in.readString();
        int size = in.readInt();
        for(int i=0;i<size;i++)
            //this does not work
            items.add(T.CREATOR.createFromParcel(in));
    }

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

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

2 に答える 2

1

<T extends Parcelable>この方法が必要な代わりに、 それ<T extends ShushContainer<T> & Parcelable>を指定して、TメソッドShushContainerと変数にアクセスできるようにします。

public class ShushContainer<T extends ShushContainer<T> & Parcelable> 
implements Parcelable

使用例はこちらSerializable

class Sample<T extends Sample<T> & Serializable> implements Serializable {

  public static int CONST = 0;

   public void foo()
   {
     T.CONST = 5;
   }
}

アップデート

私が正しく理解している場合、それを実装する別のクラスがあります。静的変数に対して動的ポリモーフィズムを試みParcelableていCREATOR ますが、これは不可能です。

どのように失敗するかを示すサンプル例

public class Base {
    public static int count = 10;
}

public class Child extends Base {
    public static int count = 20;
}


class Sample<T extends Base> {
    T t = null;
    public void printCount() {
        System.out.println(T.count);
    }
    public Sample(T t) {
        this.t = t;
    }

    public static void main(String[] args) {
        Sample<Child> sample = new Sample<Child>(new Child());
        Sample<Base> sample1 = new Sample<Base>(new Base());
        sample.printCount();//Child value printed as 10
        sample1.printCount();//Same for parent value printed as  10
    }

}

静的フィールドはインスタンスではなくクラスにバインドされているため、このプログラムは失敗します。そのため、値にアクセスすると、2 つの別個countの 1 つの forBaseと 1 つのfor が存在し、常に 10 になります。ChildBase

リフレクションを使用して、CREATORフィールドが存在するかどうかを確認してアクセスできます。これは、オブジェクトまたはクラス オブジェクトなしでは不可能です。

または、 TypeTokenを使用して以下のようなことができます

class Sample<T extends Serializable> implements Serializable {

    public int abc = 0;
    public void foo() {
    }
    public static void main(String[] args) throws SecurityException, NoSuchFieldException {
        TypeToken<Sample<Integer>> token = new TypeToken<Sample<Integer>>() {
        };
        Class<?> t = token.getRawType();
        Field field = t.getDeclaredField("abc");
        field.setAccessible(true);
        System.out.println(field.getName());

    }
}
于 2012-09-26T12:52:44.377 に答える
0

これは、静的 CREATOR プロパティにアクセスする方法に関する質問には答えませんが、Parcelable を実装するこのプロパティにアクセスする必要はありません。以下に例を示します。

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

    dest.writeInt(items.size());
    for(int i=0;i<items.size();i++)
        items.get(i).writeToParcel(dest, flags);
}

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-20T08:51:23.903 に答える