抽象类作为parcelable

基本上,我有我的应用程序中的以下结构:

uml我的应用程序

没有抽象类ProjectItem就可以直接实现这样的结构,但在这种情况下,我不知道如何实现这个。

抽象类ProjectItem需要一个CREATOR因为它应该是可分段的。 (如in.readTypedList(mProjectItems, ProjectItem.CREATOR);在构造函数Project(Parcel in)中

但实际上,出于逻辑的原因, CREATOR只能在派生类中实现。

那么,如何实现这个结构才能保持类Project可见性?

编辑

这是Project的构造函数之一:

 private Project(Parcel in) { in.readTypedList(mProjectItems, ProjectItem.CREATOR); } 

但正如我已经说过的, ProjectItem不应该实现一个CREATOR

所选的答案(来自evertvandenbruel的文章)有一个错误。 只有其中一个子类被分类时,正确的代码必须考虑分类,而不仅仅是超类对象的列表。

所有其他的代码应该是相同的,关键是你必须在所有创build者的typesvariables中读取(见下面的代码)。 否则,在尝试去除一个子类对象的时候会遇到sorting问题

例如:

 package com.example.parcelable_example.model; import android.os.Parcel; import android.os.Parcelable; public class Cat extends Animal{ public Cat(String name){ super(name, "Cat"); } public int describeContents() { return this.hashCode(); } public void writeToParcel(Parcel dest, int flags) { dest.writeString(getType()); super.writeToParcel(dest, flags); } public Cat(Parcel source) { super(source); } public static final Parcelable.Creator<Cat> CREATOR = new Parcelable.Creator<Cat>() { public Cat createFromParcel(Parcel in) { /** DO NOT FORGET THIS!!! **/ type = in.readString(); return new Cat(in); } public Cat[] newArray(int size) { return new Cat[size]; } }; } 

我的解决scheme类似于evertvandenbruel的。 但是我使用int来标识具体类,以便我可以使用开关块。 我也有一个静态的getConcreteClass(Parcel)方法的开关块。

AbstractClass.java

 public abstract class AbstractClass implements Parcelable { public static final int CLASS_TYPE_ONE = 1; public static final int CLASS_TYPE_TWO = 2; public static final Creator<AbstractClass> CREATOR = new Creator<AbstractClass>() { @Override public AbstractClass createFromParcel(Parcel source) { return AbstractClass.getConcreteClass(source); } @Override public AbstractClass[] newArray(int size) { return new AbstractClass[size]; } }; protected String mAbstractClassString; public AbstractClass(String abstractClassString) { mAbstractClassString = abstractClassString; } public AbstractClass(Parcel source) { mAbstractClassString = source.readString(); } public static AbstractClass getConcreteClass(Parcel source) { switch (source.readInt()) { case CLASS_TYPE_ONE: return new ConcreteClassOne(source); case CLASS_TYPE_TWO: return new ConcreteClassTwo(source); default: return null; } } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(mAbstractClassString); } @Override public String toString() { return "Parent String: " + mAbstractClassString + '\n'; } } 

ConcreteClassOne.java

 public class ConcreteClassOne extends AbstractClass { private String mString; public ConcreteClassOne(String abstractClassMemberString, String string) { super(abstractClassMemberString); mString = string; } public ConcreteClassOne(Parcel source) { super(source); mString = source.readString(); } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(CLASS_TYPE_ONE); super.writeToParcel(dest, flags); dest.writeString(mString); } @Override public String toString() { return super.toString().concat("Child String: " + mString); } } 

ConcreteClassTwo.java

 public class ConcreteClassTwo extends AbstractClass { private String mString; private int mInt; public ConcreteClassTwo(String abstractClassString, String string, int anInt) { super(abstractClassString); mString = string; mInt = anInt; } public ConcreteClassTwo(Parcel source) { super(source); mString = source.readString(); mInt = source.readInt(); } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(CLASS_TYPE_TWO); super.writeToParcel(dest, flags); dest.writeString(mString); dest.writeInt(mInt); } @Override public String toString() { String string = super.toString(); for (int i = 0; i < mInt; i++) { string = string.concat("Child String: " + mString + '\n'); } return string; } } 
 public abstract class A implements Parcelable { private int a; protected A(int a) { this.a = a; } public void writeToParcel(Parcel out, int flags) { out.writeInt(a); } protected A(Parcel in) { a = in.readInt(); } } public class B extends A { private int b; public B(int a, int b) { super(a); this.b = b; } public static final Parcelable.Creator<B> CREATOR = new Parcelable.Creator<B>() { public B createFromParcel(Parcel in) { return new B(in); } public B[] newArray(int size) { return new B[size]; } }; public int describeContents() { return 0; } }