读写 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:

ERROR/AndroidRuntime (5880) : 由 java.lang. ClassCastException: [ Landroid.os.Parcelable;

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

更新:

将对象数组转换为 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?

74756 次浏览

ERROR/AndroidRuntime (5880) : 由 java.lang. ClassCastException: [ Landroid.os.Parcelable;

根据 空气污染指数,readParcelableArray 方法返回 Parcelable array (Parcelable []) ,它不能简单地转换为 MyClass array (MyClass [])。

但是现在我得到了 Null Pointer 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);
}

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

MyClass[] mObjList;


public void writeToParcel(Parcel out) {
out.writeTypedArray(mObjList, 0);
}


private void readFromParcel(Parcel in) {
mObjList = in.createTypedArray(MyClass.CREATOR);
}

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

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

我也遇到过类似的问题,就这样解决了。 我在 MyClass 中定义了一个 helper 方法,用于将 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"));

编辑 : 这是同一个函数的一个更新版本,我最近使用它来避免编译警告:

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

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

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);
}