如何在使用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类,它也有IntegerBoolean字段,这些字段可以为null。

我在使用通用的Parcel.writeValue方法时遇到了困难,特别是当我试图通过Parcel.readValue读取它时。 我不断得到一个运行时exception,说它不能找出包裹对象的types。

最终,我能够通过使用Parcel.writeSerializableParcel.readSerializabletypesParcel.writeSerializable来解决问题,因为IntegerBoolean实现了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; }