Lecture et écriture de tableaux d’objects parcellables

J’ai un cours suivant qui lit et écrit un tableau d’objects depuis / vers une plot:

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

Dans le code ci-dessus, je reçois une ClassCastException lors de la lecture de readParcelableArray :

ERROR / AndroidRuntime (5880): Causée par: java.lang.ClassCastException: [Landroid.os.Parcelable;

Qu’est-ce qui ne va pas dans le code ci-dessus? Lors de l’écriture du tableau d’objects, dois-je d’abord convertir le tableau en ArrayList ?

METTRE À JOUR:

Est-il correct de convertir un tableau Object en ArrayList et de l’append à une plot? Par exemple, lors de l’écriture:

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

En lisant:

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

Mais maintenant, je reçois une NullPointerException . Est-ce que l’approche ci-dessus est correcte? Pourquoi il lance un NPE?

Vous devez écrire le tableau à l’aide de la méthode Parcel.writeTypedArray() et le lire avec la méthode Parcel.createTypedArray() , comme ceci:

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

La raison pour laquelle vous ne devriez pas utiliser les readParcelableArray() / writeParcelableArray() est que readParcelableArray() crée vraiment un Parcelable[] en conséquence. Cela signifie que vous ne pouvez pas MyClass[] le résultat de la méthode en MyClass[] . Au lieu de cela, vous devez créer un tableau MyClass de la même longueur que le résultat et copier tous les éléments du tableau de résultats dans le tableau MyClass .

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

ERROR / AndroidRuntime (5880): Causée par: java.lang.ClassCastException: [Landroid.os.Parcelable;

Selon l’ API , la méthode readParcelableArray renvoie un tableau Parcelable (Parcelable []), qui ne peut pas être simplement converti en tableau MyClass (MyClass []).

Mais maintenant, je reçois une exception de pointeur nul.

Il est difficile de déterminer la cause exacte sans la trace détaillée de la stack des exceptions.


Supposons que vous ayez correctement implémenté les implémentations Parcelable de MyClass, comme nous le faisons habituellement pour sérialiser / désérialiser un tableau d’objects parcellables:

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

J’espère que cela t’aides.

Vous pouvez également utiliser les méthodes suivantes:

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

J’ai eu un problème similaire et l’ai résolu de cette façon. J’ai défini une méthode d’assistance dans MyClass pour convertir un tableau de Parcelable en un tableau d’objects MyClass:

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

Chaque fois que j’ai besoin de lire un tableau parcellable d’objects MyClass, par exemple d’une intention:

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

EDIT : Voici une version mise à jour de la même fonction, que j’utilise plus récemment, pour éviter les avertissements de compilation:

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

Vous devez écrire le tableau à l’aide de la méthode Parcel.writeTypedArray() et le relire avec la méthode Parcel.readTypedArray() , comme ceci:

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

Pour les listes, vous pouvez effectuer les opérations suivantes:

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