解决线上概率性异常 TransactionTooLargeException

一、问题描述

在这里插入图片描述

根据经验,看到这个问题描述,第一时间想到的是 Intent 传递了太大的数据,但是进行堆栈分析后,发现并不是我想的这样

二、堆栈分析

查看出错的堆栈

在这里插入图片描述

可以看到崩溃是出现在某个 Activity stop 的时候,跟 intent 传递数据是不符合的,查看出错的页面

在这里插入图片描述

是在 PictureSelectActivity onPaused 后崩溃的,也确实和 intent 传递数据没什么关系

从堆栈中我们可以看到调用了 BinderProxy.transact 方法,然后调用到了 native 层,我们顺腾摸瓜,最后找到了报错代码

在这里插入图片描述

在这里插入图片描述

parcelSize 只要大于 200KB,就会报错,而 parcelSize 则对应于 BinderProxy.transact 方法的 Parcel data 对象,那么问题就指向了为何 data 会超过 200KB

但是现在有个疑问是,到底要怎样才能复现崩溃呢?因为我们现在知道了报错代码,但是并不知道什么场景会报错。

三、尝试复现问题

通过对页面数据的排查,发现出错的页面都是 PictureSelectActivity,且都是在该 Activity onPause 之后出错的,那么查询代码,看 PictureSelectActivity onPause 之后做了什么呢?

可能1:

在这里插入图片描述

上面是选完图片后,通过 setResult 把数据传递回上一个 Activity,只是传了一个 urlList,数据量并不大,所以排除这个可能

可能2:

PictureSelectActivity 中有几个 Fragment,Activity 与 Fragment 之间传递数据使用了 Bundle,但是查看代码后发现传递的数据量很小,且不符合

ActivityStop 的时机,排除

可能3:

通过查阅资料

https://www.cnblogs.com/tgltt/p/9834584.html

找到另外一种可能

问题原因:FragmentStatePagerAdapter 的 saveState() 实现有缺陷,因为其默认实现会持续保存历史Fragment实例的状态数据历史,在逐渐地积累、保存数据后,最终导致发送的数据包体积超过限制200KB 。

在这里插入图片描述

saveState 被 ViewPager 的 onSaveInstanceState 调用了

在这里插入图片描述

当activity有可能被系统回收的情况下,系统将调用 Activity 的 onSaveInstanceState(Bundle outState) 进行数据的保存,以便 activity 重新创建的时候,可以恢复数据,而 Activity 的 onSaveInstanceState(Bundle outState)

被调用后会调用 View 的 onSaveInstanceState

onSaveInstanceState(Bundle outState)会在以下情况被调用:
1、当用户按下HOME键时。
2、从最近应用中选择运行其他的程序时。
3、按下电源按键(关闭屏幕显示)时。
4、从当前activity启动一个新的activity时。
5、屏幕方向切换时(无论竖屏切横屏还是横屏切竖屏都会调用)。

在前4种情况下,当前activity的生命周期为:

onPause -> onSaveInstanceState -> onStop

为了印证这种可能,我们让 PictureSelectActvity 的图片浏览器浏览了 500 张图片,然后按下 HOME 键,这时候果然出现了崩溃,也就印证了崩溃的原因了

总结:问题的原因是 当 Activity 被隐藏时,其 onSaveInstanceState(Bundle outState) 被调用进行数据的保存,最终调用了 FragmentStatePagerAdapter 的 saveState(),而 saveState() 实现有缺陷,因为其默认实现会持续保存历史Fragment实例的状态数据历史,在逐渐地积累、保存数据后,最终导致发送的数据包体积超过限制200KB 。

四、解决问题

重写 FragmentStatePagerAdapter 的 saveState() ,saveState() 的时候不保存任何的数据

加粗样式

影响范围:因为保存的数据只有在 Activity 被回收,然后恢复 Activity 的时候有用,而这种情况下不恢复之前的状态其实影响不大,所以这种方案是可行的

为了避免其他业务也出现类似的情况,所以封装出一个基类,只有那些 ViewPager 的页数比较多的场景才需要继承这个类

在这里插入图片描述

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值