【问题标题】:Implementing Parcelable interface on polymorphic arrays在多态数组上实现 Parcelable 接口
【发布时间】:2013-06-17 01:07:47
【问题描述】:

我有一个名为ItinerarySegment 的类型数组,该类型有子类:WalkSegmentBusSegment 等。

public interface ItinerarySegment
{

}

public class WalkSegment implements ItinerarySegment
{

}

public class BusSegment implements ItinerarySegment
{

}

在使ItinerarySegment 的数组可包裹时,我应该遵循什么样的策略?这里主要关心的是以后通过createTypedArray方法(由writeTypedArray方法准备)重构数组时如何使用。

其中createTypedArray 方法采用Creator 字段参数。问题出在这里...应该在哪里定义Creator 字段? (在ItinerarySegmentWalkSegmentBusSegment?)。

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 就会有问题。

需要说明吗?

【问题讨论】:

    标签: android oop inheritance serialization parcelable


    【解决方案1】:

    要使用writeTypedArray()createTypedArray() 执行此操作,您需要将ItinerarySegment 设为abstract class,而不是interfaceItinerarySegment 需要实现 Parcelable 并且需要定义一个 CREATOR 来解组 Parcel 并创建新对象。派生类还需要实现writeToParcel()describeContents()CREATOR 方法。

    注意:因为writeTypedArray() 不会将对象的类型写入Parcel,所以您需要自己执行此操作。这里有两种可能的方法:

    1. 每个派生类的writeParcel() 方法必须在一开始就向Parcel 写入一些标识其类型的内容(Stringint 值)。

    2. 每个派生类的writeParcel() 方法必须在向Parcel 写入任何内容之前调用super.writeToParcel()。在ItinerarySegment.writeToParcel() 方法中,您可以确定它是什么类型的派生类,然后向Parcel 写入一些标识其类型的内容(Stringint 值)。

    ItinerarySegment 中的CREATOR 将首先从Parcel 中读取标识符,然后使用该标识符确定要实例化的对象类型。然后它将调用相应对象的CREATOR 以实际实例化该对象并将其返回给它的调用者。

    这基本上就像一个对象工厂,其中基类知道如何实例化它自己的派生类的不同类型。

    所有这些的缺点是抽象基类必须知道它的所有派生类。我想你也可以动态地做到这一点,让所有派生类调用基类中的一个静态方法,传递它的“类型”和CREATOR,然后基类将其存储在一个数组中以供需要时使用。

    一切可行,但相当复杂。

    作为替代方案,您可以使用writeParcelableArray()readParcelableArray(),其中每个对象的类名都写入Parcel,以便在解组时知道要调用哪个CREATOR

    恕我直言,使用writeTypedArray()createTypedArray() 的唯一时间是当数组中的所有对象都是同一类的实例,并且您将其中的几个写入Parcel 时。在这种情况下,您可以节省将类名写入每个对象的Parcel 的开销,因为您知道它们都是相同的。在这种情况下,您不需要经历我上面描述的所有痛苦,因为您事先知道所有对象的类型(没有多态类型)。

    我意识到这个答案可能晚了一年多,但到底是什么。也许它会帮助别人;-)

    【讨论】:

    • 我意识到这条评论晚了一年多:-) 但是,是的,你的回答很有帮助。我想知道 Java 如何将多态包裹解压成正确的类型……现在我明白它没有。 :-( 很遗憾,但是您建议的工厂方法应该可行。
    猜你喜欢
    • 1970-01-01
    • 2013-07-17
    • 2016-09-09
    • 1970-01-01
    • 1970-01-01
    • 2011-09-06
    • 1970-01-01
    • 2015-12-13
    • 1970-01-01
    相关资源
    最近更新 更多