我有一个名为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字段的方法,则后续子类的数据将丢失,因为它们的构造函数均未使用Parcel参数调用,而是将调用ItinerarySegment的构造函数.
constructor(Parcel in);
如果我让WalkSegment定义Creator字段,那么BusSegment将有问题.
需要澄清吗?
解决方法:
为了使用writeTypedArray()和createTypedArray()进行此 *** 作,您需要将ItinerarySegment设为抽象类,而不是接口. ItinerarySegment需要实现Parcelable,并且需要定义一个CREATOR,然后调用该CREATOR来解组Parcel并创建新对象.派生类还需要实现writetoParcel(),describeContents()和CREATOR方法.
注意:因为writeTypedArray()不会将对象的类型写入包裹,所以您需要自己执行此 *** 作.这有两种可能的方法:
>每个派生类的writeParcel()方法必须在一开始就将一些内容写入Parcel,以标识其类型(String或int值).
>每个派生类的writeParcel()方法必须在将任何内容写入Parcel之前调用super.writetoParcel().在ItinerarySegment.writetoParcel()方法中,您可以弄清楚它是什么类型的派生类,然后向Parcel中写入一些内容以标识其类型(字符串或int值).
ItinerarySegment中的CREATOR将首先从包裹中读取标识符,然后使用该标识符确定要实例化的对象类型.然后它将调用相应对象的CREATOR来实际实例化该对象并将其返回给其调用者.
这基本上像对象工厂一样工作,其中基类知道如何实例化其自己的派生类的不同类型.
所有这些的缺点是抽象基类必须了解其所有派生类.我想您还可以动态地执行此 *** 作,方法是让所有派生类在基类中调用静态方法,并传递其“类型”和CREATOR,然后将其存储在数组中以根据需要使用.
都可行,但是非常复杂.
作为替代方案,您可以使用writeParcelableArray()和readParcelableArray(),其中将每个对象的类名写入Parcel,以便在解组时知道要调用哪个CREATOR.
恕我直言,只有在数组中的所有对象都是同一类的实例时,才使用writeTypedArray()和createTypedArray(),并且您要在Parcel中写入多个对象.在这种情况下,您可以节省为每个对象将类名写入Parcel的开销,因为您知道它们都是相同的.在这种情况下,您不需要经历我上面描述的所有痛苦,因为您事先知道了所有对象的类型(没有多态类型).
我知道这个答案可能迟到一年多了,但那太麻烦了.也许会帮助别人;-)
总结以上是内存溢出为你收集整理的android-在多态数组上实现Parcelable接口全部内容,希望文章能够帮你解决android-在多态数组上实现Parcelable接口所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)