79

パーセルとの間でオブジェクトの配列を読み書きする次のクラスがあります。

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

上記のコードではClassCastException、読み取り時に次のようになりますreadParcelableArray

エラー/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を投げているのですか?

4

4 に答える 4

164

次のように、メソッドを使用して配列を書き込み、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()実際に a が作成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);
}
于 2012-05-28T07:51:05.223 に答える
12

同様の問題があり、この方法で解決しました。Parcelable の配列を MyClass オブジェクトの配列に変換するために、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);
}
于 2013-04-10T06:49:36.883 に答える
5

次のように、メソッドを使用して配列を書き込み、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);
  }
于 2015-04-01T09:33:33.360 に答える