Lectura y escritura de matrices de objetos Parcelable

Tengo la siguiente clase que lee y escribe una matriz de objetos desde / hacia un paquete:

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 CREATOR = new Parcelable.Creator() { public ClassABC createFromParcel(Parcel in) { return new ClassABC(in); } public ClassABC[] newArray(int size) { return new ClassABC[size]; } }; } 

En el código anterior, obtengo una ClassCastException cuando leo readParcelableArray :

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

¿Qué está mal en el código anterior? Al escribir la matriz de objetos, ¿debo convertir primero la matriz a una ArrayList ?

ACTUALIZAR:

¿Está bien convertir una matriz de Objetos en una ArrayList y agregarla a plot? Por ejemplo, al escribir:

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

Al leer:

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

Pero ahora obtengo una NullPointerException . ¿El enfoque anterior es correcto? ¿Por qué está arrojando un NPE?

Debes escribir la matriz usando el método Parcel.writeTypedArray() y leerla de nuevo con el método Parcel.createTypedArray() , así:

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

La razón por la que no debe usar los readParcelableArray() / writeParcelableArray() es que readParcelableArray() realmente crea un Parcelable[] como resultado. Esto significa que no puede convertir el resultado del método en MyClass[] . En su lugar, debe crear una matriz MyClass de la misma longitud que el resultado y copiar cada elemento de la matriz de resultados a la matriz MyClass .

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

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

De acuerdo con la API , el método readParcelableArray devuelve la matriz Parcelable (Parcelable []), que no se puede convertir simplemente a la matriz MyClass (MyClass []).

Pero ahora recibo la excepción del puntero nulo.

Es difícil decir la causa exacta sin el rastreo detallado de la stack de excepción.


Supongamos que ha hecho los implementos MyClass Parcelable correctamente, así es como solemos hacer para serializar / deserializar una matriz de objetos plotbles:

 public class ClassABC implements Parcelable { private List 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(); in.readList(mObjList, getClass().getClassLoader()); } public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { public ClassABC createFromParcel(Parcel in) { return new ClassABC(in); } public ClassABC[] newArray(int size) { return new ClassABC[size]; } }; } 

Espero que esto ayude.

También puede usar los siguientes métodos:

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

Tuve un problema similar y lo resolví de esta manera. Definí un método auxiliar en MyClass, para convertir una matriz de Parcelable en una matriz de objetos MyClass:

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

Cada vez que necesito leer una matriz plotble de objetos MyClass, por ejemplo, de un bash:

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

EDITAR : Aquí hay una versión actualizada de la misma función, que estoy usando más recientemente, para evitar advertencias de comstackción:

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

Parcel.writeTypedArray() escribir la matriz utilizando el método Parcel.writeTypedArray() y leerla de nuevo con el método Parcel.readTypedArray() , así:

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

Para las listas, puede hacer lo siguiente:

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