这节课看下使用 startActivity 时都有哪些需要注意的点。
1. taskAffinity
通过设置不同的启动模式可以实现调配不同的 Task。但是 taskAffinity 在一定程度上也会影响任务栈的调配流程。
taskAffinity 会默认使 Activity 在新的栈中分配吗?
结论:单纯使用 taskAffinity 不能导致 Activity 被创建在新的任务栈中,需要配合 singleTask 或者 singleInstance!
taskAffinity + allowTaskReparenting
allowTaskReparenting 赋予 Activity 在各个 Task 中间转移的特性。一个在后台任务栈中的 Activity A,当有其他任务进入前台,并且 taskAffinity 与 A 相同,则会自动将 A 添加到当前启动的任务栈中。
2. 通过 Binder 传递数据的限制
在 startFirstB 方法中,跳转 FirstB 页面,并通过 Intent 传递 Bean 类中的数据。但是会报错,log 日志的意思是 Intent 传递数据过大,最终原因是 Android 系统对使用 Binder 传数据进行了限制。通常情况为 1M
解决办法:
- 减少通过 Intent 传递的数据,将非必须字段使用
transient
关键字修饰。 - 将对象转化为 JSON 字符串,减少数据体积。 因为 JVM 加载类通常会伴随额外的空间来保存类相关信息,将类中数据转化为 JSON 字符串可以减少数据大小。比如使用 Gson.toJson 方法。
大多时候,将类转化为 JSON 字符串之后,还是会超出 Binder 限制,说明实际需要传递的数据是很大的。这种情况则需要考虑使用本地持久化来实现数据共享,或者使用 EventBus 来实现数据传递。
3. process 造成多个 Application
Activity 可以在不同的进程中启动,而每一个不同的进程都会创建出一个 Application,因此有可能造成 Application 的 onCreate 方法被执行多次。
- onCreate 方法中判断进程的名称,只有在符合要求的进程里,才执行初始化操作;
- 抽象出一个与 Application 生命周期同步的类,并根据不同的进程创建相应的 Application 实例。
4. 后台启动 Activity 失效
试想一下,如果我们正在玩着游戏,此时手机后台可能有个下载某 App 的任务在执行。当 App 下载完之后突然弹出安装界面,中断了游戏界面的交互,这种情况会造成用户体验极差,而最终用户的吐槽对象都会转移到 Android 手机或者 Android 系统本身。
解决办法: Android 官方建议我们使用通知来替代直接启动 Activity 操作
也就是当后台执行的任务执行完毕之后,并不会直接调用 startActivity 来启动新的界面,而是通过 NotificationManager 来发送 Notification 到状态栏。这样既不会影响当前使用的交互操作,用户也能及时获取后台任务的进展情况,后续的操作由用户自己决定。
总结
本课时主要总结了几个使用 startActivity 时可能会遇到的问题:
- taskAffinity 实现任务栈的调配;
- 通过 Binder 传递数据的限制;
- 多进程应用可能会造成的问题;
- 后台启动 Activity 的限制。