我有一个名为ItinerarySegment
的数组,这个类型有子类:WalkSegment
,BusSegment
等。
public interface ItinerarySegment
{
}
public class WalkSegment implements ItinerarySegment
{
}
public class BusSegment implements ItinerarySegment
{
}
在制作ItinerarySegment
数组时,我应该遵循什么样的策略?这里主要关注的是在以后通过createTypedArray方法(由writeTypedArray方法准备)重构数组时如何使用它。
createTypedArray方法采用Creator字段参数。问题出在这里...... Creator字段应该定义在哪里? (在ItinerarySegment
,WalkSegment
或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字段的方法,那么随后的子类的数据将会丢失,因为它们的构造函数都不会被调用将调用宗地参数,而不是ItinerarySegment
的构造函数。
constructor(Parcel in);
如果我WalkSegment
定义Creator字段,则BusSegment
会出现问题。
需要澄清吗?
答案 0 :(得分:3)
要使用writeTypedArray()
和createTypedArray()
执行此操作,您需要将ItinerarySegment
设为abstract class
,而不是interface
。 ItinerarySegment
需要实现Parcelable
,并且需要定义一个CREATOR
来调用Parcel
解组并创建新对象。派生类还需要实现方法writeToParcel()
,describeContents()
和CREATOR
。
注意:由于writeTypedArray()
不会将对象的类型写入Parcel
,因此您需要自己执行此操作。这有两种可能的方式:
每个派生类的writeParcel()
方法必须在一开始就向Parcel
写一些标识其类型的内容(String
或int
值)。
每个派生类的writeParcel()
方法必须在向super.writeToParcel()
写入任何内容之前调用Parcel
。在ItinerarySegment.writeToParcel()
方法中,您可以确定它是什么类型的派生类,并向Parcel
写一些标识其类型(String
或int
值)的内容。< / p>
CREATOR
中的ItinerarySegment
将首先从Parcel
读取标识符,然后使用该标识符确定要实例化的对象类型。然后它会调用相应对象的CREATOR
来实际实例化对象并将其返回给它的调用者。
这基本上就像一个对象 factory ,其中基类知道如何实例化不同类型的自己的派生类。
所有这些的缺点是抽象基类必须知道它的所有派生类。我想你也可以通过让所有派生类在基类中调用一个静态方法来传递它的“类型”和CREATOR
,然后基类将存储在一个数组中以便根据需要使用它。
一切都可行,但非常复杂。
作为替代方案,您可以使用writeParcelableArray()
和readParcelableArray()
,其中每个对象的类名都写入Parcel
,以便它知道在CREATOR
时调用哪个writeTypedArray()
解组。
恕我直言,唯一一次使用createTypedArray()
和Parcel
的情况是,数组中的所有对象都是同一个类的实例,并且您正在将少数几个对象写入{{1} }}。在这种情况下,您可以节省将类名写入每个对象的Parcel
的开销,因为您知道它们都是相同的。在这种情况下,您不需要经历我上面描述的所有痛苦,因为您事先知道所有对象的类型(没有多态类型)。
我意识到这个答案可能已经晚了一年多了,但是到底是什么。也许它会帮助别人; - )