Using Parcelable with circular references

亡梦爱人 提交于 2019-12-03 00:20:17

Perhaps the answer lies in a more intelligent set of writeToParcel and createFromParcel methods?

Off the top of my head, you could keep a list of objects you had already fully written to a given Parcel and identify them only by a tag (their local identityHashCode(), perhaps). (Note that this is not a global list, it is explicitly per-Parcel; perhaps itself stored via a semi-global Map<Parcel,Set<Integer> > ? You'd need to be sure the set was forgotten once the parcel was fully written.)

The relevant bit of writeToParcel() would look something like this:

HashSet<Integer> set = getWrittenSetFor(dest);
final int tag = identityHashCode();
if (set.contains(tag)) {
    // Already sent
    dest.writeInt(tag);
} else {
    set.put(tag);
    dest.writeInt(tag);
    dest.writeValue(this);
}

The corresponding createFromParcel() would be slightly more complex.

I expect there are lurking problems with this method, but it's where I'd start. As I've put it here, it depends on identityHashCode() being guaranteed to be different for different objects - it usually is on 32-bit JVMs (being the value of the underlying C++ pointer). Plain hashCode() might be worthwhile (perhaps with the addition of typing information?), or perhaps some sort of serial number.

Another option might be to just plain serialize your objects to a byte[] and write that into the Parcel, but it strikes me as a bit inefficient...

Use Java serialization. Make your class extend Externalizable instead of Parcelable and convert it to byte array using ObjectOutputStream. Pass this byte array to other side [1] [2] and deserialize it using ObjectInputStream.

Android Parcelables are very fast, but that speed comes at cost of all extra functionality, traditionally present in serialization frameworks.

Java serialization was designed to be powerful and flexible and includes support for many things including handling circular references. If you declare custom serialVersionUID (to avoid it's reflective computation at runtime) and manually read/write class contents in readExternal/writeExternal, you will get almost same performance as with Parcelable (where "almost" is spent on keeping track of circular references and such).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!