问题引入
在开发高德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异常
异常产生
还有两种情况会抛出异常:
-
使用 Bundle 传递大量数据:Bundle 对象常用于在 Activity、Fragment 和 Service 之间传递数据。但是,如果 Bundle 中的数据量过大,同样会引发此异常。
-
进程间通信(IPC)传递大量数据:在进行跨进程通信时,如果传递的数据量过大,也会触发此异常。
异常的影响
-
应用崩溃
-
直接导致应用崩溃:如果
TransactionTooLargeException
没有被正确捕获和处理,它可能会导致应用程序意外终止或崩溃,给用户带来不好的体验。 -
Activity重启:在某些情况下,比如设备旋转导致的配置变化,
onSaveInstanceState()
方法中保存的数据过大也会引发此异常,进而造成 Activity 的非正常销毁和重启。
-
-
数据丢失或不一致
-
数据丢失:由于异常的发生,可能导致正在传输的数据未能成功到达目标端,从而引起数据丢失问题。
-
状态不一致:对于依赖于 IPC 来保持状态同步的应用组件来说,异常会导致这些组件之间的状态不同步,影响用户体验和功能完整性。
-
-
用户体验受损
-
响应迟缓:频繁地尝试发送大量数据不仅增加了发生异常的风险,还可能让应用变得响应迟缓,因为每次失败都会触发额外的错误处理逻辑。
-
操作中断:正在进行的操作可能会突然中断,例如地图导航中的路径规划或者信息查询等关键操作无法顺利完成。
-
-
开发与调试困难
-
难以复现:有时候这种异常很难在开发环境中稳定复现,特别是在不同的设备和Android版本上表现不一,这增加了问题定位和修复的难度。
-
日志混乱:如果未正确处理异常,日志文件中可能会充斥着大量的堆栈跟踪信息,使得正常的日志记录变得难以解读。
-
解决方法
目前在网络上找到的方法大致如下:
-
优化数据传输:尽量减少在 Intent、Bundle 或 IPC 中传递的数据量。可以通过将数据拆分、使用数据库或文件系统存储等方式来优化数据传输。
-
使用共享内存:对于大量数据的传输,可以考虑使用共享内存(如 ContentProvider、FileProvider 等)来避免数据过大导致的问题。
-
优化数据结构:优化数据结构,减少冗余数据,以降低数据传输量。
可能是我比较菜,使用共享内存的时候失败了,也没找到原因,后面看了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();