Sko*_*kod 8 stack-overflow android loops parcelable chain
相当简单的场景,但我在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 );
(...)
}
}
Run Code Online (Sandbox Code Playgroud)
这将不可避免地循环并溢出堆栈.
我的问题:我应该如何处理我必须将上述类型的对象传递给新Activity的情况.
(对于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)
Run Code Online (Sandbox Code Playgroud)
这将不可避免地循环并溢出堆栈.
AFAIK,parceling过程不处理圆形对象图.我刚提交了一个问题,以便更好地记录下来.
一种解决方法是不这样做p.writeParcelable( _containerRef );.相反,在ContainerClass您的ContainerClass(Parcel in)构造函数中(或者您CREATOR正在处理它),在读取_items列表后,迭代该列表并告诉每个孩子其父项.
我一直在思考更多问题,并提出了两种有用的解决方法,如果其他人也有同样的情况:
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 );
(...)
}
}
Run Code Online (Sandbox Code Playgroud)
2) Hackish 解决方法,使用静态哈希表,授予每个对象可以通过其可分割属性唯一标识。(就我而言,我的数据库中有对象的主键)。
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 );
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2384 次 |
| 最近记录: |