读写Parcelable对象的数组

我有下面的类,它读/写一个包裹对象的数组:

class ClassABC extends Parcelable { MyClass[] mObjList; private void readFromParcel(Parcel in) { mObjList = (MyClass[]) in.readParcelableArray( com.myApp.MyClass.class.getClassLoader())); } public void writeToParcel(Parcel out, int arg1) { out.writeParcelableArray(mObjList, 0); } private ClassABC(Parcel in) { readFromParcel(in); } public int describeContents() { return 0; } public static final Parcelable.Creator<ClassABC> CREATOR = new Parcelable.Creator<ClassABC>() { public ClassABC createFromParcel(Parcel in) { return new ClassABC(in); } public ClassABC[] newArray(int size) { return new ClassABC[size]; } }; } 

在上面的代码中,当读取readParcelableArray时,我得到一个ClassCastException

错误/ AndroidRuntime(5880):引起:java.lang.ClassCastException:[Landroid.os.Parcelable;

上面的代码有什么错? 在写对象数组的时候,我应该先把数组转换成一个ArrayList

更新:

将Object数组转换为ArrayList并将其添加到宗地可以吗? 例如,写作时:

  ArrayList<MyClass> tmpArrya = new ArrayList<MyClass>(mObjList.length); for (int loopIndex=0;loopIndex != mObjList.length;loopIndex++) { tmpArrya.add(mObjList[loopIndex]); } out.writeArray(tmpArrya.toArray()); 

阅读时:

  final ArrayList<MyClass> tmpList = in.readArrayList(com.myApp.MyClass.class.getClassLoader()); mObjList= new MyClass[tmpList.size()]; for (int loopIndex=0;loopIndex != tmpList.size();loopIndex++) { mObjList[loopIndex] = tmpList.get(loopIndex); } 

但是现在我得到一个NullPointerException 。 以上方法是否正确? 为什么要扔NPE?

您需要使用Parcel.writeTypedArray()方法编写数组,然后使用Parcel.writeTypedArray()方法读取数组,如下所示:

 MyClass[] mObjList; public void writeToParcel(Parcel out) { out.writeTypedArray(mObjList, 0); } private void readFromParcel(Parcel in) { mObjList = in.createTypedArray(MyClass.CREATOR); } 

您不应该使用readParcelableArray() / writeParcelableArray()方法的原因是, readParcelableArray()实际上创build了一个readParcelableArray() Parcelable[] 。 这意味着你不能将方法的结果转换为MyClass[] 。 相反,您必须创build一个与结果长度相同的MyClass数组,并将结果数组中的每个元素复制到MyClass数组中。

 Parcelable[] parcelableArray = parcel.readParcelableArray(MyClass.class.getClassLoader()); MyClass[] resultArray = null; if (parcelableArray != null) { resultArray = Arrays.copyOf(parcelableArray, parcelableArray.length, MyClass[].class); } 

错误/ AndroidRuntime(5880):引起:java.lang.ClassCastException:[Landroid.os.Parcelable;

根据API ,readParcelableArray方法返回Parcelable数组(Parcelable []),它不能被简单地转换为MyClass数组(MyClass [])。

但是现在我得到空指针exception。

没有详细的exception堆栈跟踪,很难确切的原因。


假设你已经使MyClass正确地实现了Parcelable,我们通常是这样做的:对一个parcelable对象进行序列化/反序列化:

 public class ClassABC implements Parcelable { private List<MyClass> mObjList; // MyClass should implement Parcelable properly // ==================== Parcelable ==================== public int describeContents() { return 0; } public void writeToParcel(Parcel out, int flags) { out.writeList(mObjList); } private ClassABC(Parcel in) { mObjList = new ArrayList<MyClass>(); in.readList(mObjList, getClass().getClassLoader()); } public static final Parcelable.Creator<ClassABC> CREATOR = new Parcelable.Creator<ClassABC>() { public ClassABC createFromParcel(Parcel in) { return new ClassABC(in); } public ClassABC[] newArray(int size) { return new ClassABC[size]; } }; } 

希望这可以帮助。

您还可以使用以下方法:

  public void writeToParcel(Parcel out, int flags) { out.writeTypedList(mObjList); } private ClassABC(Parcel in) { mObjList = new ArrayList<ClassABC>(); in.readTypedList(mObjList, ClassABC.CREATOR); } 

我有类似的问题,并通过这种方式解决。 我在MyClass中定义了一个帮助器方法,用于将一个Parcelable数组转换为一个MyClass对象数组:

 public static MyClass[] toMyObjects(Parcelable[] parcelables) { MyClass[] objects = new MyClass[parcelables.length]; System.arraycopy(parcelables, 0, objects, 0, parcelables.length); return objects; } 

无论何时我需要读取一个可见的MyClass对象数组,例如从一个意图:

 MyClass[] objects = MyClass.toMyObjects(getIntent().getParcelableArrayExtra("objects")); 

编辑 :这是我最近使用的相同function的更新版本,以避免编译警告:

 public static MyClass[] toMyObjects(Parcelable[] parcelables) { if (parcelables == null) return null; return Arrays.copyOf(parcelables, parcelables.length, MyClass[].class); } 

您需要使用Parcel.writeTypedArray()方法编写数组,然后使用Parcel.writeTypedArray()方法读取数组,如下所示:

 MyClass[] mObjArray; public void writeToParcel(Parcel out, int flags) { out.writeInt(mObjArray.length); out.writeTypedArray(mObjArray, flags); } protected MyClass(Parcel in) { int size = in.readInt(); mObjArray = new MyClass[size]; in.readTypedArray(mObjArray, MyClass.CREATOR); } 

对于列表,您可以执行以下操作:

  ArrayList<MyClass> mObjList; public void writeToParcel(Parcel out, int flags) { out.writeTypedList(mObjList); } protected MyClass(Parcel in) { mObjList = new ArrayList<>(); //non-null reference is required in.readTypedList(mObjList, MyClass.CREATOR); }