真的很简单,但是我在Google上找不到任何相关内容,所以这里有:
class ContainerClass implements Parcelable {
List<ItemClass> _items;
(...)
public void writeToParcel( Parcel p, int args ) {
p.writeList( _items );
(...)
}
}
class ItemClass implements Parcelable {
ContainerClass _containerRef;
(...)
public void writeToParcel( Parcel p, int args ) {
p.writeParcelable( _containerRef );
(...)
}
}
这将不可避免地循环并溢出堆栈。
我的问题:我应该如何处理我必须将上述类型的对象传递给新活动的情况。
(对于CommonsWare)Parcelable实现确实似乎没有检查,并避免循环依赖。 具有由上述名称替换的类名的Stacktrace:
08-12 10:17:45.233 5590-5590/com.package E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.StackOverflowError
at com.package.ContainerClass.writeToParcel(ContainerClass.java:139)
at android.os.Parcel.writeParcelable(Parcel.java:1254)
at com.package.ItemClass.writeToParcel(ItemClass.java:182)
at android.os.Parcel.writeParcelable(Parcel.java:1254)
at android.os.Parcel.writeValue(Parcel.java:1173)
at android.os.Parcel.writeList(Parcel.java:622)
at com.package.ContainerClass.writeToParcel(ContainerClass.java:144)
at android.os.Parcel.writeParcelable(Parcel.java:1254)
at com.package.ItemClass.writeToParcel(ItemClass.java:182)
at android.os.Parcel.writeParcelable(Parcel.java:1254)
at android.os.Parcel.writeValue(Parcel.java:1173)
at android.os.Parcel.writeList(Parcel.java:622)
答案 0 :(得分:9)
这将不可避免地循环并溢出堆栈。
AFAIK,parceling进程无法处理circular object graphs。我刚刚提交了an issue to get this better documented。
一种解决方法是不执行p.writeParcelable( _containerRef );
。相反,在ContainerClass
中,在ContainerClass(Parcel in)
构造函数中(或者您的CREATOR
正在处理它),在阅读_items
列表后,迭代该列表并告诉每个孩子关于它的父母。
答案 1 :(得分:1)
如果其他人在同一条船上,我一直在思考更多并提出两个有用的解决方法:
1)(受CommonsWare启发) 在链的每个部分放置一个标志以指示方向 在这种意义上,层次结构是有损的,因为无法恢复ContainerClass的所有项目。
class ContainerClass implements Parcelable {
boolean _parcelableDownHeirarchy = true;
List<ItemClass> _items;
(...)
private ContainerClass( Parcel in ) {
_items = in.readArrayList( ItemClass.class.getClassLoader() );
(...)
if ( _parcelableDownHierarchy ) {
for ( int i = 0; i < _items.size(); i++ )
_items.get( i ).set_container( this );
}
}
public void writeToParcel( Parcel p, int args ) {
p.writeByte( (byte)_parcelableDownHierarchy ? 1 : 0 );
if ( _parcelableDownHeirarchy )
p.writeList( _items );
(...)
}
}
class ItemClass implements Parcelable {
boolean _parcelableDownHeirarchy = true;
ContainerClass _containerRef;
(...)
private ItemClass( Parcel in ) {
if ( !_parcelableDownHeirarchy ) {
_containerRef = in.readParcelable( ContainerClass.class.getClassLoader() );
//Won't contain item in it's _items list.
}
}
public void writeToParcel( Parcel p, int args ) {
p.writeByte( (byte)_parcelableDownHierarchy ? 1 : 0 );
if ( !_parcelableDownHeirarchy ) //Up the heirarchy
p.writeParcelable( _containerRef );
(...)
}
}
2)Hackish变通方法,使用静态哈希表,授予每个对象可以由它的parcelable属性唯一标识。 (在我的例子中,我在对象中的数据库中有主键)。
class ContainerClass implements Parcelable {
//Leave be
}
class ItemClass implements Parcelable {
HaspMap<Long, ContainerClass> _parents = new HashMap<Long, ContainerClass>();
ContainerClass _containerRef;
(...)
public long get_PKhash() { /* Return unique identifier */ }
private ItemClass( Parcel in ) {
(...)
assertTrue( (_containerRef = _parents.remove( get_PKhash() )) != null );
}
public void writeToParcel( Parcel p, int args ) {
(...)//Don't write _containerRef
_parents.put( this.get_PKhash, _containerRef );
}
}