如何在使用Parcelable接口时序列化空值

igo*_*lic 60 android nullpointerexception parcelable

关于我的代码示例,如果一个Locable的变量为null,我会做什么?例如,现在如果l.getZoom()返回null,我得到NullPointerException.

@Override
public void writeToParcel(Parcel parcel, int arg1) {
    parcel.writeInt(count);
    for(Locable l:locableArr){
        parcel.writeInt(l.getOriginId());
        parcel.writeInt(l.getLocableType());
        parcel.writeInt(l.getZoom());
        parcel.writeDouble(l.getLatituda());
        parcel.writeDouble(l.getLongituda());
        parcel.writeString(l.getTitle());
        parcel.writeString(l.getSnipet());
    }

}
Run Code Online (Sandbox Code Playgroud)

谢谢!

art*_*tch 103

您可以使用Parcel.writeValue带有空值的编组通用对象.

  • 然后读取值... s =(String)in.readValue(String.class.getClassLoader()); (49认同)
  • @SofiSoftwareLLC看着parcel.readValue的源代码,只需要对地图类型,Parcelable,ArrayList的类加载器,对象[]和Parcelable [].对于其他类型,您可以为类加载器传入null.https://github.com/android/platform_frameworks_base/blob/3bdbf644d61f46b531838558fabbd5b990fc4913/core/java/android/os/Parcel.java#L2002 (2认同)

小智 20

我正在使用Parcelable具有IntegerBoolean字段的类,并且这些字段可以为null.

我在使用泛型Parcel.writeValue方法时遇到了麻烦,特别是当我试图通过它读取它时Parcel.readValue.我一直得到一个运行时异常,说它无法弄清楚所包含对象的类型.

最终,我还是能够通过使用来解决问题Parcel.writeSerializable,并Parcel.readSerializable用一个类型转换,既IntegerBoolean实现Serializable接口.read和write方法null为您处理值.


Fel*_*ima 14

这是我想出的安全编写字符串的解决方案:

private void writeStringToParcel(Parcel p, String s) {
    p.writeByte((byte)(s != null ? 1 : 0));
    p.writeString(s);
}

private String readStringFromParcel(Parcel p) {
    boolean isPresent = p.readByte() == 1;
    return isPresent ? p.readString() : null;
}
Run Code Online (Sandbox Code Playgroud)

  • 只有当它不为空时,才应该使用行`p.writeString(s)`来编写字符串; 否则你会在这一行得到一个NullPointerException. (3认同)

Dav*_*ser 13

我见过的大多数序列化代码都使用标志来指示值的存在/不存在或者在带有计数字段的值之前(例如,在写入数组时),如果值不是,则count字段刚刚设置为零. t存在.

检查Android核心类的源代码会显示这样的代码(来自Message类):

    if (obj != null) {
        try {
            Parcelable p = (Parcelable)obj;
            dest.writeInt(1);
            dest.writeParcelable(p, flags);
        } catch (ClassCastException e) {
            throw new RuntimeException(
                "Can't marshal non-Parcelable objects across processes.");
        }
    } else {
        dest.writeInt(0);
    }
Run Code Online (Sandbox Code Playgroud)

或者这个(来自Intent类):

    if (mCategories != null) {
        out.writeInt(mCategories.size());
        for (String category : mCategories) {
            out.writeString(category);
        }
    } else {
        out.writeInt(0);
    }
Run Code Online (Sandbox Code Playgroud)

我的建议:在你的代码中,如果"zoom == null"和"zoom == 0"之间没有功能差异,那么我只是将缩放声明为原语(int而不是Integer)或者在构造函数中将其初始化为零并且确保你永远不会将它设置为null(然后你可以保证它永远不会为null,你不必在序列化/反序列化方法中添加特殊代码来处理它).