4

という名前の型の配列がありItinerarySegment、この型にはサブクラスがあります:WalkSegmentなどBusSegment

public interface ItinerarySegment
{

}

public class WalkSegment implements ItinerarySegment
{

}

public class BusSegment implements ItinerarySegment
{

}

ItinerarySegmentparcelableの配列を作成する場合、どのような戦略に従う必要がありますか? ここでの主な関心事は、createTypedArrayメソッド ( writeTypedArrayメソッドによって準備される) を介して配列を再構築するときに後でどのように使用されるかということです。

ここで、createTypedArrayメソッドはCreatorフィールド パラメータを受け取ります。ここに問題があります... Creatorフィールドはどこに定義する必要がありますか? ( ItinerarySegmentWalkSegment、またはBusSegment?)。

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

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

};

ItinerarySegment抽象クラスを作成して Creator フィールドのメソッドを定義すると、後続のサブクラスのデータが失われます。これは、Parcel パラメーターを使用してコンストラクターが呼び出されず、代わりにItinerarySegmentのコンストラクターが呼び出されるためです。

constructor(Parcel in);

CreatorフィールドをWalkSegment定義すると、問題が発生します。BusSegment

明確化が必要ですか?

4

1 に答える 1

4

を使用してこれを行うには、ではなくを作成する必要がありwriteTypedArray()ます。実装する必要があり、アンマーシャリングして新しいオブジェクトを作成するために呼び出される定義済みが必要です。派生クラスもメソッドを実装する必要があります。createTypedArray()ItinerarySegmentabstract classinterfaceItinerarySegmentParcelableCREATORParcelwriteToParcel()describeContents()CREATOR

注:writeTypedArray()はオブジェクトの型を に書き込まないためParcel、自分で行う必要があります。考えられる方法は 2 つあります。

  1. 各派生クラスのメソッドは、その型 (aまたは値)を識別する最初の部分にwriteParcel()何かを書き込む必要があります。ParcelStringint

  2. に何かを書き込む前にwriteParcel()、各派生クラスのメソッドを呼び出す必要があります。このメソッドでは、派生クラスの型を特定し、その型 (aまたは値)を識別する何かを に書き込むことができます。super.writeToParcel()ParcelItinerarySegment.writeToParcel()ParcelStringint

CREATORinItinerarySegmentは最初に から識別子を読み取り、それParcelを使用してインスタンス化するオブジェクトのタイプを決定します。次に、対応するオブジェクトを呼び出して、CREATOR実際にオブジェクトをインスタンス化し、それを呼び出し元に返します。

これは基本的にオブジェクトファクトリのように機能し、基底クラスは独自の派生クラスのさまざまなタイプをインスタンス化する方法を知っています。

このすべての欠点は、抽象基本クラスがその派生クラスのすべてを認識しなければならないことです。これを動的に行うこともできると思います。すべての派生クラスが基本クラスの静的メソッドを呼び出して、その「型」と を渡します。CREATOR基本クラスは、必要に応じて使用する配列に格納します。

すべて実行可能ですが、かなり複雑です。

writeParcelableArray()代わりにandを使用できますreadParcelableArray()。ここでは、各オブジェクトのクラス名が に書き込まれるため、アンマーシャリング時にParcelどちらを呼び出すかがわかります。CREATOR

IMHO を使用する唯一の時間writeTypedArray()createTypedArray()、配列内のすべてのオブジェクトが同じクラスのインスタンスであり、Parcel. その場合、Parcelすべて同じであることがわかっているため、クラス名を for each オブジェクトに書き込むオーバーヘッドを節約できます。この場合、すべてのオブジェクトの型が事前にわかっているため (ポリモーフィック型ではない)、上で説明したすべての苦労を経験する必要はありません。

この答えはおそらく1年以上遅れていると思いますが、一体何でしょう。多分それは他の誰かを助けるでしょう;-)

于 2015-02-08T12:14:28.980 に答える