记录我解决TransactionTooLargeException的经验(非典型)

首先容我吐槽一下,这个异常也太坑爹了,最开始看到的时候完全摸不到头脑,然后扒了好多篇文章,也没头绪。绝大部分文章都再说Intent的事,少部分讲了dialog可能引发的问题。这里我就不赘述这些典型问题了。
下面只介绍一下我遇到的问题,我个人认为我遇到的问题并不典型,做个记录,以后可能还会遇到。

首先crash日志如下:
实际上日志里面基本上是别指望看出什么东西了,根本没有本应用的堆栈信息。

2019-05-16 23:45:44.577 6394-6394/com.example.lenovo.raispaceandroid E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.lenovo.raispaceandroid, PID: 6394
    java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 617364 bytes
        at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3826)
        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:6239)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:895)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:785)
     Caused by: android.os.TransactionTooLargeException: data parcel size 617364 bytes
        at android.os.BinderProxy.transactNative(Native Method)
        at android.os.BinderProxy.transact(Binder.java:615)
        at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:3657)
        at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3818)
        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:6239) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:895) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:785) 

如开头所说,我确实看了不少解决该问题的文章,但是很不幸,没有跟我的情况相符的。
最典型的Intent携带数据过大的问题,我在发生crash的位置反复排查,根本没有这种迹象。
我使用的Intent基本上没有携带过大规模数据,基本上都是int或者boolean之类的,没道理Intent连这种数据都吃不消。

于是我仔细分析了一下Crash的场景,都是从主页面开启一个新的页面(设置页)之后,1-2秒左右才发生的Crash,所以此时可以断定跟跳转的Intent是没关系的,那么这里短短的时间内发生了什么呢?

继续分析:
首先我进入设置页之后全部都是没有进行任何操作,而且进来之后程序并非必然崩溃,那么问题不在这个页面,那么只可能是因为进入设置页之前的场景不同了。

由于我的主页Activity内部是由FragmentStack来实现的,简单来说,就是各个Fragment来回跳转,所以打开设置页之前,当前栈顶的Fragment并不一样,所以有时崩溃,有时不崩溃。

所以我就让每个Fragment都作为栈顶,进入设置页,看是否崩溃。最终定位到一个Fragment,只要该Fragment位于栈顶,那么跳转页面之后,必然会发生崩溃。。。实际上在开启新的Activity之后,上一个Activity中的Fragment都会调用onSaveInstanceState(Bundle outState)方法,而其实Intent不能传递较大的数据,也跟Bundle的数据大小限制有关,是否与此有关呢。

我看了看着个Fragment,确实保存的数据太大了,于是把保存的逻辑删除重试了一下,再也没有发生崩溃,然后用其他方式,代替onSaveInstanceState的作用即可。

总结

本次问题总结成一句话就是:在Fragment的onSaveInstanceState(Bundle outState)方法中,不可给Bundle存入过大的数据,否则随后就会抛出TransactionTooLargeException这个让人头大的异常。
Activity的onSaveInstanceState方法一样也要注意。

你可能感兴趣的:(记录我解决TransactionTooLargeException的经验(非典型))