如何使用ArrayList <Parcelable>正确实现Parcelable?


76

我上课很难Parcelable。麻烦的是,我正在尝试将包裹中的一个成员写入ArrayList<Parcelable>对象,这是一个对象。的ArrayListSerializable,和对象(ZigBeeDev)在列表中的Parcelable

以下是相关代码:

package com.gnychis.coexisyst;

import java.util.ArrayList;
import java.util.Iterator;

import android.os.Parcel;
import android.os.Parcelable;

public class ZigBeeNetwork implements Parcelable {

    public String _mac;             // the source address (of the coordinator?)
    public String _pan;             // the network address
    public int _band;               // the channel
    ArrayList<Integer> _lqis;       // link quality indicators (to all devices?)
    ArrayList<ZigBeeDev> _devices;  // the devices in the network

    public void writeToParcel(Parcel out, int flags) {
        out.writeString(_mac);
        out.writeString(_pan);
        out.writeInt(_band);
        out.writeSerializable(_lqis);
        out.writeParcelable(_devices, 0);  // help here
    }

    private ZigBeeNetwork(Parcel in) {
        _mac = in.readString();
        _pan = in.readString();
        _band = in.readInt();
        _lqis = (ArrayList<Integer>) in.readSerializable();
        _devices = in.readParcelable(ZigBeeDev.class.getClassLoader());  // help here
    }

    public int describeContents() {
        return this.hashCode();
    }

    public static final Parcelable.Creator<ZigBeeNetwork> CREATOR = 
            new Parcelable.Creator<ZigBeeNetwork>() {
        public ZigBeeNetwork createFromParcel(Parcel in) {
            return new ZigBeeNetwork(in);
        }

        public ZigBeeNetwork[] newArray(int size) {
            return new ZigBeeNetwork[size];
        }
    };

    //...
}

我在“ //帮助这里”标记了两个点,以了解如何正确地写包裹以及如何对其进行重建。如果ZigBeeDev经过Parcelable(正确测试),我该如何正确执行?

Answers:


143

您差点知道了!

您只需要做:

public void writeToParcel(Parcel out, int flags) {
    out.writeString(_mac);
    out.writeString(_pan);
    out.writeInt(_band);
    out.writeSerializable(_lqis);
    out.writeTypedList(_devices);
}

private ZigBeeNetwork(Parcel in) {
    _mac = in.readString();
    _pan = in.readString();
    _band = in.readInt();
    _lqis = (ArrayList<Integer>) in.readSerializable();
    in.readTypedList(_devices, ZigBeeDev.CREATOR);
}

就这样!

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

out.writeList(_lqis);
_lqis = new ArrayList<>();
in.readList(_lqis Integer.class.getClassLoader());

它应该工作。


2
供将来参考,我不确定这是否是没有人注意到的错别字,但ZigBeeDev.Creator应该是ZigBeeDev.CREATOR。每次我都出错,直到我意识到我可以在自己的项目中使用两个不同的创作者。
gatlingxyz 2014年

@ NitroG42阅读列表的第二种方法导致cannot convert from void to ArrayList<Integer>
AlexAndro 2014年

8
我还需要实例化数组,示例代码如下所示:_devices = new ArrayList <ZigBeeDev>(); in.readTypedList(_devices,ZigBeeDev.Creator);
sgarman

@sgarman无需实例化数组原因,然后您会收到警告:显式类型参数ZigBeeDev可以替换为<>此检查报告所有带有类型参数的新表达式,都可以将其替换为菱形类型<>
crubio

确认要Hashtable使用String为其键或值使用原始类型(包括)的泛型。
Eido95 '17

17

在我的情况in.readTypedList(_devices, ZigBeeDev.CREATOR);给我一个NullPointerException_devices。所以我用了这个:

_devices = in.createTypedArrayList(ZigBeeDev.CREATOR);

3
fwiw-收到NPE的原因是,如果使用NPE,则in.readTypedList()需要先创建一个新的ArrayList(),然后将其传递给in.readTypedList(yourNewArrayList, YourObj.CREATOR)否则,它将仅尝试将数据放入空列表中。
rf43

对,那是正确的。在使用之前,我已经阅读了源代码。感谢您提供我忘记写的其他信息。
osrl

当遵循您的解决方案时,@ osrl出现异常java.lang.OutOfMemoryError:未能分配13893804字节分配,其中包含11004100可用字节和10MB,直到OOM
Ajit Kumar Dubey

您的阵列中是否保存文件或其他大型文件?@Ajit
osrl 2016年



0

有点晚了,但我也遇到了这个问题。经过长时间的浪费,我偶然发现了parcelabler.com网站,该网站会自动为您创建包裹。

它使我可以很容易地在内部创建带有数组列表的嵌套宗地,从而节省了很多时间。

基本上,网站的工作方式是您在其中输入带有ArrayList的对象,然后它会自动添加必要的方法以使其可包裹(从包裹中读取,写入包裹,描述内容以及包裹创建者都是自动生成的)。这在创建复杂的宗地时特别有用,例如在这里提出的问题,其中包含嵌套的宗地,数组和列表。

编辑:IntelliJ IDEA和Android Studio也为此具有插件,它们与列出的网站具有相似的功能:

这些插件根据类中的字段生成Android Parcelable样板代码。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.