欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

TransactionTooLargeException解决与分析

程序员文章站 2022-01-30 20:48:22
...
1、前言:

前段时间线上突然间报了一个问题,从页面详情页(以下简称页面A)跳转图片浏览页(以下简称页面B),发生崩溃,但是只有个别的页面A跳转页面B发生崩溃,后来通过查询崩溃日志发现一个异常:
TransactionTooLargeException

2、问题排查:

通过查询代码,发现是因为页面B跳转页面B通过Bundle传递了Parcelable对象,但是通过
Bundle传递Parcelable大小限制为1M,超出1M就会报TransactionTooLargeException

3、解决方案:
  • 1、改为使用EventBus传递大数据(简单,快速)
  • 2、使用单例存储并获取对象(效率低)
  • 3、将数据通过文件存储,从另外一个页面读取(io操作)
  • 4、原因分析:
  • 代码案例
    val intent = Intent(this, MyActivity::class.java).apply {
        putExtra("extra", "abc")
    }
    startActivity(intent)
步骤分解:
  • 1、操作系统将intent的Extra参数通过Bundle打包
  • 2、操作系统创建新的Activity,将数据拆包,并将intent传递给新Activity
  • 3、由于Bundle类针对使用parcel进行编组和解组进行了高度优化,自定义对象实现Parcelable传递对象,效率较高
  • 4、新Activity通过getParcelable可以获取Parceable对象内容
底层逻辑:
  • 由于Activity通过intent传值,是通过App进程将intent携带的数据传输到AMS进程,最终通过Binder事务缓冲区完成数据传输
  • 目前Binder事务缓冲区的大小固定有限,目前为1MB,进程中正在处理的所有事务共享
  • 由于此限制是进程级别而不是Activity级别的限制,因此这些事务包括应用中的所有 binder 事务,超过大小限制时,将引发TransactionTooLargeException。
文档说明

The Binder transaction buffer has a limited fixed size, currently 1MB, which is shared by all transactions in progress for the process. Consequently this exception can be thrown when there are many transactions in progress even when most of the individual transactions are of moderate size.

5、参考:

1、Parcelable 和 Bundle

2、TransactionTooLargeException

3、TransactionTooLargeException异常