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