得到了android.os.TransactionTooLargeException,据说是因为
“当同时通过Parcel传输过多数据时会发生此异常。底层Binder事务缓冲区具有有限的固定大小,当前为1Mb,由进程正在进行的所有事务共享。因此,即使大多数单个事务的大小适中,当有许多事务正在进行时,也会抛出此异常。“
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可能保存的数据。
日志显示所有这些片段的视图总共可以节省不到30k。
所以不知道这个“数据包大小593484字节”来自哪里。
或者必须有一些其他数据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;
}
}