Android 读取和写入 Parcelable 对象数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10071502/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 02:22:52  来源:igfitidea点击:

Read & writing arrays of Parcelable objects

androidparcelable

提问by User7723337

I have following class which reads and writes an array of objects from/to a parcel:

我有以下类从/向包裹读取和写入对象数组:

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

In above code I get a ClassCastExceptionwhen reading readParcelableArray:

在上面的代码中,我ClassCastException在阅读时得到了一个readParcelableArray

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

错误/AndroidRuntime(5880):引起:java.lang.ClassCastException:[Landroid.os.Parcelable;

What is wrong in above code? While writing the object array, should I first convert the array to an ArrayList?

上面的代码有什么问题?在编写对象数组时,我应该先将数组转换为ArrayList?

UPDATE:

更新:

Is it OK to convert an Object array to an ArrayListand add it to parcel? For instance, when writing:

将 Object 数组转换为 anArrayList并将其添加到parcel 是否可以?例如,在编写时:

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

When reading:

阅读时:

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

But now I get a NullPointerException. Is above approach is correct? Why it is throwing an NPE?

但现在我得到了一个NullPointerException. 以上方法是否正确?为什么它会抛出 NPE?

回答by Michael

You need to write the array using the Parcel.writeTypedArray()method and read it back with the Parcel.createTypedArray()method, like so:

您需要使用该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);
}

The reason why you shouldn't use the readParcelableArray()/writeParcelableArray()methods is that readParcelableArray()really creates a Parcelable[]as a result. This means you cannot cast the result of the method to MyClass[]. Instead you have to create a MyClassarray of the same length as the result and copy every element from the result array to the MyClassarray.

你不应该使用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);
}

回答by yorkw

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

错误/AndroidRuntime(5880):引起:java.lang.ClassCastException:[Landroid.os.Parcelable;

According to the API, readParcelableArray method returns Parcelable array (Parcelable[]), which can not be simply casted to MyClass array (MyClass[]).

根据API,readParcelableArray 方法返回Parcelable 数组(Parcelable[]),不能简单地强制转换为MyClass 数组(MyClass[])。

But now i get Null Pointer Exception.

但现在我得到空指针异常。

It is hard to tell the exact cause without the detailed exception stack trace.

如果没有详细的异常堆栈跟踪,很难说出确切的原因。



Suppose you have made MyClass implements Parcelable properly, this is how we usually do for serialize/deserialize a array of parcelable objects:

假设您已经让 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];
    }
  };

}

Hope this helps.

希望这可以帮助。

You can also use the following methods:

您还可以使用以下方法:

  public void writeToParcel(Parcel out, int flags) {
      out.writeTypedList(mObjList);
  }

  private ClassABC(Parcel in) {
      mObjList = new ArrayList<ClassABC>();
      in.readTypedList(mObjList, ClassABC.CREATOR);
  }

回答by Giorgio Barchiesi

I had a similar problem, and solved it this way. I defined a helper method in MyClass, for converting an array of Parcelable to an array of MyClass objects:

我有一个类似的问题,并以这种方式解决了它。我在 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;
}

Whenever I need to read a parcelable array of MyClass objects, e.g. from an intent:

每当我需要读取 MyClass 对象的可分割数组时,例如从意图中:

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

EDIT: Here is an updated version of the same function, that I am using more recently, to avoid compile warnings:

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

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

回答by EpicPandaForce

You need to write the array using the Parcel.writeTypedArray()method and read it back with the Parcel.readTypedArray()method, like so:

您需要使用该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);
}

For lists, you can do the following:

对于列表,您可以执行以下操作:

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