首先看看Logcat日志如下:
1Caused by: android.os.TransactionTooLargeException: data parcel size 1278400 bytes
2at android.os.BinderProxy.transactNative(Native Method)
3at android.os.BinderProxy.transact(BinderProxy.java:532)
4at android.app.IActivityTaskManager$Stub$Proxy.activityStopped(IActivityTaskManager.java:4561)
5at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:145)
6at android.os.Handler.handleCallback(Handler.java:900)
7at android.os.Handler.dispatchMessage(Handler.java:103)
8at android.os.Looper.loop(Looper.java:219)
9at android.app.ActivityThread.main(ActivityThread.java:8347)
10at java.lang.reflect.Method.invoke(Native Method)
11at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
12at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1055)
原因分析
从上述日志可以看出。出现问题的原因是因为binder
事务发送和接收的序列化对象过大,超过binder
上限时,就会抛出该异常。
Google定义的上限时1M,但这是对整个进程的所有binder事务定义的,单个binder传递是小于该值的。
Android7.0之前该异常并不会影响app运行,之后会报以上异常。
出现场景
- intent跳转时,bundle携带的数据量过大(比如,传递一个超大的数据集合或者bitmap)
- Activity或Fragment执行onSaveInstanceState保存过多数据
分析工具
使用github上大佬提供的专门用于分析调试TransactionTooLargeException
的工具toolargetool
toolargetool
A tool for debugging TransactionTooLargeException on Android.
https://github.com/guardian/toolargetool
解决办法
-
根据Google建议,Activity跳转时intent携带的数据不要过大
-
特别留意
onSavedInstanceState
场景,尽量避免过大的数据被保存 -
Fragment传递数据时,限制setArguments里的数据量过大
实际应用
我们有一个需求,使用ViewPager2实现直播间纵滑功能。
当切换的直播间比较多时,该bug可能会被触发造成崩溃。
我们首先在项目中引入toolargetool
库进行分析(引入忽略,github上有详细接入流程)
我们使用adb logcat -s ToolargeTool
检测一下日志输出
12-02 16:35:33.087 16961 16961 D TooLargeTool: LivePlayerPageActivity.onSaveInstanceState wrote: Bundle131394213 contains 5 keys and measures 19.0 KB when serialized as a Parcel
12-02 16:35:33.087 16961 16961 D TooLargeTool: * android:viewHierarchyState = 1.0 KB
12-02 16:35:52.402 16961 16961 D TooLargeTool: LivePlayerPageActivity.onSaveInstanceState wrote: Bundle140574781 contains 5 keys and measures 57.8 KB when serialized as a Parcel
12-02 16:35:52.402 16961 16961 D TooLargeTool: * android:viewHierarchyState = 14.2 KB
12-02 16:36:23.626 16961 16961 D TooLargeTool: LivePlayerPageActivity.onSaveInstanceState wrote: Bundle216803432 contains 5 keys and measures 83.2 KB when serialized as a Parcel
12-02 16:36:23.626 16961 16961 D TooLargeTool: * android:viewHierarchyState = 37.2 KB
12-02 16:37:12.587 16961 16961 D TooLargeTool: LivePlayerPageActivity.onSaveInstanceState wrote: Bundle91071570 contains 5 keys and measures 118.5 KB when serialized as a Parcel
12-02 16:37:12.587 16961 16961 D TooLargeTool: * android:viewHierarchyState = 76.1 KB
12-02 16:37:37.113 16961 16961 D TooLargeTool: LivePlayerPageActivity.onSaveInstanceState wrote: Bundle45092331 contains 5 keys and measures 166.8 KB when serialized as a Parcel
12-02 16:37:37.113 16961 16961 D TooLargeTool: * android:viewHierarchyState = 122.2 KB
12-02 16:39:31.786 16961 16961 D TooLargeTool: LivePlayerPageActivity.onSaveInstanceState wrote: Bundle267655365 contains 5 keys and measures 202.2 KB when serialized as a Parcel
12-02 16:39:31.786 16961 16961 D TooLargeTool: * android:viewHierarchyState = 159.7 KB
根据日志可以看出,当我们切换(纵滑)了多次直播间之后,android:viewHierarchyState = 122.2 KB
值一直是增加的,当这个值增加到大约超过500kb时就会爆出该异常。
这里我们大概就能确定,造成该异常的直接原因就是viewpager2嵌入了Fragment,每切换一次Viewpager2,Fragment中的保存的状态就会增加
最简单的解决办法就是不保存状态。在我们的viewpager2中增加该代码android:saveEnabled="false"
网友评论