安卓开发Binder Intent数据溢出问题-TransactionTooLargeException

问题引入

在开发高德APP时,创建了一个Activity显示导航的具体信息,比如**路直行200米右转进入***路,具体显示如下:

使用跳转的代码:

        final DrivePath drivePath = driveRouteResult.getPaths().get(0);
        
        //跳转到路线详情页面
        binding.tvDetail.setOnClickListener(v -> {
            Intent intent = new Intent(MainActivity.this,
                    RouteDetailActivity.class);
            intent.putExtra("type",2);
//            intent.putExtra("path", drivePath);
            startActivity(intent);
        });

intent.putExtra("path", drivePath);原本的逻辑是intent携带类型数据与路线数据跳转到新的Activity,通常情况是没错的,但是路线过长,导航信息变多了,而intent携带的数据必须少于1MB,因为自身有一部分数据,超过后会抛出:TransactionTooLargeException。

TransactionTooLargeException异常

异常产生

还有两种情况会抛出异常:

  1. 使用 Bundle 传递大量数据:Bundle 对象常用于在 Activity、Fragment 和 Service 之间传递数据。但是,如果 Bundle 中的数据量过大,同样会引发此异常。

  2. 进程间通信(IPC)传递大量数据:在进行跨进程通信时,如果传递的数据量过大,也会触发此异常。

异常的影响

  1. 应用崩溃

    1. 直接导致应用崩溃:如果 TransactionTooLargeException 没有被正确捕获和处理,它可能会导致应用程序意外终止或崩溃,给用户带来不好的体验。

    2. Activity重启:在某些情况下,比如设备旋转导致的配置变化,onSaveInstanceState() 方法中保存的数据过大也会引发此异常,进而造成 Activity 的非正常销毁和重启。

  2. 数据丢失或不一致

    1. 数据丢失:由于异常的发生,可能导致正在传输的数据未能成功到达目标端,从而引起数据丢失问题。

    2. 状态不一致:对于依赖于 IPC 来保持状态同步的应用组件来说,异常会导致这些组件之间的状态不同步,影响用户体验和功能完整性。

  3. 用户体验受损

    1. 响应迟缓:频繁地尝试发送大量数据不仅增加了发生异常的风险,还可能让应用变得响应迟缓,因为每次失败都会触发额外的错误处理逻辑。

    2. 操作中断:正在进行的操作可能会突然中断,例如地图导航中的路径规划或者信息查询等关键操作无法顺利完成。

  4. 开发与调试困难

    1. 难以复现:有时候这种异常很难在开发环境中稳定复现,特别是在不同的设备和Android版本上表现不一,这增加了问题定位和修复的难度。

    2. 日志混乱:如果未正确处理异常,日志文件中可能会充斥着大量的堆栈跟踪信息,使得正常的日志记录变得难以解读。

解决方法

目前在网络上找到的方法大致如下:

  1. 优化数据传输:尽量减少在 Intent、Bundle 或 IPC 中传递的数据量。可以通过将数据拆分、使用数据库或文件系统存储等方式来优化数据传输。

  2. 使用共享内存:对于大量数据的传输,可以考虑使用共享内存(如 ContentProvider、FileProvider 等)来避免数据过大导致的问题。

  3. 优化数据结构:优化数据结构,减少冗余数据,以降低数据传输量。

可能是我比较菜,使用共享内存的时候失败了,也没找到原因,后面看了EventBus,这个方式简单,且能传大数据(超过1MB),在这给个链接,感兴趣的可以看看:

EventBus(事件总线)的使用和源码的简单解析-优快云博客

不过我使用的比较简单,首先在需要创建自定义消息的类,然后在接收消息的Activity注册EventBus,再创建消息的处理函数::

import com.amap.api.services.route.DrivePath;

public class DrivePathMes {
    public DrivePath drivePath;

    public DrivePathMes(DrivePath drivePath) {
        this.drivePath = drivePath;
    }

    public static DrivePathMes getInstance(DrivePath drivePath) {
        return new DrivePathMes(drivePath);
    }

}

最后在需要的地方添加发送操作:

// 发布 DrivePathMes 事件
EventBus.getDefault().postSticky(DrivePathMes.getInstance(drivePath));

注意:

        可能由于版本的差异,使用起来可能会有些许的不同,我当前的版本使用EventBus发送消息是收不到的,最后查了几篇文章,发现需要添加EventBus的初始化代码才行,我的是添加在MainActivity的oncreate里面:

EventBus.builder().installDefaultEventBus();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值