如何在使用Parcelable接口时序列化空值
关于我的代码示例,如果一个Locable的variables为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()); } }
谢谢!
您可以使用Parcel.writeValue
对具有空值的通用对象进行编组。
我所见过的大多数序列化代码都使用标志来指示是否存在一个值,或者在计数字段之前(例如,当写入数组时)在值的前面,如果计数字段只是设置为零,根本不存在。
检查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); }
或者这个(来自Intent类):
if (mCategories != null) { out.writeInt(mCategories.size()); for (String category : mCategories) { out.writeString(category); } } else { out.writeInt(0); }
我的build议:在你的代码中,如果“zoom == null”和“zoom == 0”之间没有function上的区别,那么我只是将缩放声明为一个原语( int
而不是Integer
),或者将它初始化为零并确保你永远不会将它设置为null(那么你可以保证它永远不会是null,你不需要添加特殊的代码来处理你的序列化/反序列化方法)。
我使用了一个Parcelable
类,它也有Integer
和Boolean
字段,这些字段可以为null。
我在使用通用的Parcel.writeValue
方法时遇到了困难,特别是当我试图通过Parcel.readValue
读取它时。 我不断得到一个运行时exception,说它不能找出包裹对象的types。
最终,我能够通过使用Parcel.writeSerializable
和Parcel.readSerializable
typesParcel.writeSerializable
来解决问题,因为Integer
和Boolean
实现了Serializable接口。 读取和写入方法为您处理null
值。
这是我想出来安全地写string的解决scheme:
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; }