4

得到了android.os.TransactionTooLargeException,据说是因为

“当同时通过 Parcels 传输过多数据时,会发生此异常。底层 Binder 事务缓冲区有一个有限的固定大小,目前为 1Mb,由该进程正在进行的所有事务共享。因此,当有许多事务正在进行时,即使大多数单个事务的大小适中,也可能会引发此异常。”</p>

   android.os.TransactionTooLargeException: data parcel size 593484 bytes
   at android.os.BinderProxy.transactNative(Binder.java)
   at android.os.BinderProxy.transact(Binder.java:628)
   at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:4132)
   at android.app.ActivityThread$StopInfo.run(ActivityThread.java:4159)
   at android.os.Handler.handleCallback(Handler.java:751)
   at android.os.Handler.dispatchMessage(Handler.java:95)
   at android.os.Looper.loop(Looper.java:154)
   at android.app.ActivityThread.main(ActivityThread.java:6692)
   at java.lang.reflect.Method.invoke(Method.java)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358)

在它崩溃的时候,日志显示 mainActivity 启动 onSaveInstanceState() 并且它还包含一些片段。

  583   |   04:46:32:173 (UTC)  | MainActivity:onSaveInstanceState()
  584   |   04:46:32:174 (UTC)  | DataListFragment:onSaveInstanceState()
  585   |   04:46:32:174 (UTC)  | DrawerFragment:onSaveInstanceState()
  586   |   04:46:32:174 (UTC)  | DataContainerFragment:onSaveInstanceState()
  587   |   04:46:32:174 (UTC)  | DataDetailsFragment:onSaveInstanceState()
  588   |   04:46:32:175 (UTC)  | DataDetailsFragment:onSaveInstanceState()
  589   |   04:46:32:175 (UTC)  | DataDetailsFragment:onSaveInstanceState()

mainActivity 有一个 Drawer 和一个列表片段,当单击列表项时,会打开一个容器片段,该容器片段具有一个 viewPage 并包含三个详细信息片段。

看起来累积的数据已经超过了 Binder 的 1 meg 限制。

在他们的 onSaveInstanceState() 调用中仔细查看了所有片段保存的数据,它们都很小(int、boolean 等),加起来不到几 k,比如说 < 10k。

还查看了所有片段的布局文件,其中使用了 LiniearLayout、TextView、ImageView、WebView 等。并做了一个日志来查看 android View 可能保存的数据。

日志显示所有这些片段的 Views 总共可以节省不到 30k。

所以不知道这个“data parcel size 593484 bytes”是从哪里来的。

或者必须有一些其他数据android系统也在保存(?)。

有没有办法找出或转储“底层 Binder 事务缓冲区”数据以查看它们可能来自什么?有谁知道 android 对 WebView 所说的数据是什么(或如何找到)?

===

扩展视图来做日志,类似的用于片段中使用的其他视图

public class LogLinearLayout extends LinearLayout {

public LogLinearLayout(Context context) {
    super(context);
}

public LogLinearLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public LogLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

@Override
protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {

    super.dispatchSaveInstanceState(container);

    for (int i = 0; i < container.size()-1; i++) {
        Parcelable val = (Parcelable)container.get(i);

        byte[] bytes = val != null ? marshall(val) : null;
        String parcelByte = (bytes != null) ? "bytes.length:"+bytes.length : ("val==null");

        if(bytes != null) {
            //Log container level the bytes.length
        }

    }
}

@Override
protected Parcelable onSaveInstanceState() {
    Parcelable pVal = super.onSaveInstanceState();

    byte[] bytes = pVal != null ? marshall(pVal) : null;
    String parcelByte = (bytes != null) ? "bytes.length:"+bytes.length : ("val==null");

    if (bytes != null) {
        //Log the bytes.length of this view
    }

    return pVal;
}

byte[] marshall(Parcelable parceable) {
        Parcel parcel = Parcel.obtain();
        parceable.writeToParcel(parcel, 0);
        byte[] bytes = parcel.marshall();
        parcel.recycle();
        return bytes;
}

}

4

0 回答 0