安卓parcelable引用另一个parcelable循环依赖parcelable

2023-09-06 04:28:18 作者:心易碎、请勿碰

而简单的场景真的,但我无法找到任何关于谷歌相关的所以这里有云:

 类ContainerClass实现Parcelable {
  名单< itemClass时> _items;
  (...)

  公共无效writeToParcel(包裹磷,INT参数){
    p.writeList(_items);
    (...)
  }
}

类itemClass时实现Parcelable {
  ContainerClass _containerRef;
  (...)

  公共无效writeToParcel(包裹磷,INT参数){
    p.writeParcelable(_containerRef);
    (...)
  }
}
 

这将不可避免地循环,使栈溢出。

我的问题:我怎么处理的情况下我必须通过一个新的活动来传递上述类型的对象

(对于CommonsWare)Parcelable实施确实似乎没有检查,避免循环依赖。 堆栈跟踪与类名由上面的名字改为:

  10月八号至12日:17:45.233 5590-5590 / com.package E / AndroidRuntime:致命异常:主要
        java.lang.StackOverflowError
        在com.package.ContainerClass.writeToParcel(ContainerClass.java:139)
        在android.os.Parcel.writeParcelable(Parcel.java:1254)
        在com.package.ItemClass.writeToParcel(ItemClass.java:182)
        在android.os.Parcel.writeParcelable(Parcel.java:1254)
        在android.os.Parcel.writeValue(Parcel.java:1173)
        在android.os.Parcel.writeList(Parcel.java:622)
        在com.package.ContainerClass.writeToParcel(ContainerClass.java:144)
        在android.os.Parcel.writeParcelable(Parcel.java:1254)
        在com.package.ItemClass.writeToParcel(ItemClass.java:182)
        在android.os.Parcel.writeParcelable(Parcel.java:1254)
        在android.os.Parcel.writeValue(Parcel.java:1173)
        在android.os.Parcel.writeList(Parcel.java:622)
 

解决方案

我一直在琢磨一些,并拿出两个解决方法很有用,如果别人是在同一条船上:

1)(由CommonsWare启发) 把一个标志链上的指示方向的各部分 向上的层次结构是有损耗的,即所有项目的ContainerClass无法恢复。

 类ContainerClass实现Parcelable {
  布尔_parcelableDownHeirarchy = TRUE;
  名单< itemClass时> _items;
  (...)

  私人ContainerClass(包裹中){
    _items = in.readArrayList(ItemClass.class.getClassLoader());
    (...)

    如果(_parcelableDownHierarchy){
      的for(int i = 0; I< _items.size();我++)
        _items.get(我).set_container(本);
    }
  }

  公共无效writeToParcel(包裹磷,INT参数){
    p.writeByte((字节)_parcelableDownHierarchy?1:0);
    如果(_parcelableDownHeirarchy)
      p.writeList(_items);

    (...)
  }
}


类itemClass时实现Parcelable {
  布尔_parcelableDownHeirarchy = TRUE;
  ContainerClass _containerRef;
  (...)

  私人itemClass时(宗地中){
    如果(!_parcelableDownHeirarchy){
      _containerRef = in.readParcelable(ContainerClass.class.getClassLoader());
      //将不包含的项目,在它的_items名单。
    }
  }

  公共无效writeToParcel(包裹磷,INT参数){
    p.writeByte((字节)_parcelableDownHierarchy?1:0);
    如果(!_parcelableDownHeirarchy)//向上的层次结构
      p.writeParcelable(_containerRef);

    (...)
  }
}
 
iOS 性能调优,成为一名合格iOS程序员必须掌握的技能

2)hackish的解决方法,采用静态的哈希表,授予每个对象都可以被唯一确定的是parcelable属性。 (在我来说,我已经在对象在我的数据库中的主键)。

 类ContainerClass实现Parcelable {
  //许可,不得
}


类itemClass时实现Parcelable {
  HaspMap<长,ContainerClass> _parents =新的HashMap<长,ContainerClass>();
  ContainerClass _containerRef;
  (...)

  公共长get_PKhash(){/ *返回唯一标识符* /}

  私人itemClass时(宗地中){
    (...)
    assertTrue((_containerRef = _parents.remove(get_PKhash()))!= NULL);
  }

  公共无效writeToParcel(包裹磷,INT参数){
    (...)//不要写_containerRef
    _parents.put(this.get_PKhash,_containerRef);
  }
}
 

Rather simple scenario really, but I could not find anything related on Google so here goes:

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 );
    (...)
  }      
}

This will inevitably loop and overflow the stack.

My question: How am I supposed to deal with a situation where I have to pass an object of the above types through to a new Activity.

(For CommonsWare) Parcelable implementation does indeed not seem to check for, and avoid circular dependencies. Stacktrace with classnames replaced by above names:

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)

解决方案

I've been pondering some more and come up with two workarounds useful if anyone else is in the same boat:

1) (Inspired by CommonsWare) Put a flag on each part of the chain to indicate direction Up the heirarchy is lossy in the sense that all items to the ContainerClass cannot be restored.

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 workaround, employing a static hash table, granted each object can be uniquely identified by it's parcelable attributes. (In my case I have the primary key in my database in the objects).

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 );
  }      
}