第13讲:Android 是如何通过 Activity 进行交互的?

176 阅读3分钟

这节课看下使用 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

解决办法:

  1. 减少通过 Intent 传递的数据,将非必须字段使用 transient 关键字修饰。
  2. 将对象转化为 JSON 字符串,减少数据体积。 因为 JVM 加载类通常会伴随额外的空间来保存类相关信息,将类中数据转化为 JSON 字符串可以减少数据大小。比如使用 Gson.toJson 方法。

大多时候,将类转化为 JSON 字符串之后,还是会超出 Binder 限制,说明实际需要传递的数据是很大的。这种情况则需要考虑使用本地持久化来实现数据共享,或者使用 EventBus 来实现数据传递。

3. process 造成多个 Application

Activity 可以在不同的进程中启动,而每一个不同的进程都会创建出一个 Application,因此有可能造成 Application 的 onCreate 方法被执行多次。

  1. onCreate 方法中判断进程的名称,只有在符合要求的进程里,才执行初始化操作;
  2. 抽象出一个与 Application 生命周期同步的类,并根据不同的进程创建相应的 Application 实例。

4. 后台启动 Activity 失效

试想一下,如果我们正在玩着游戏,此时手机后台可能有个下载某 App 的任务在执行。当 App 下载完之后突然弹出安装界面,中断了游戏界面的交互,这种情况会造成用户体验极差,而最终用户的吐槽对象都会转移到 Android 手机或者 Android 系统本身。

解决办法: Android 官方建议我们使用通知来替代直接启动 Activity 操作

也就是当后台执行的任务执行完毕之后,并不会直接调用 startActivity 来启动新的界面,而是通过 NotificationManager 来发送 Notification 到状态栏。这样既不会影响当前使用的交互操作,用户也能及时获取后台任务的进展情况,后续的操作由用户自己决定。

总结

本课时主要总结了几个使用 startActivity 时可能会遇到的问题:

  • taskAffinity 实现任务栈的调配;
  • 通过 Binder 传递数据的限制;
  • 多进程应用可能会造成的问题;
  • 后台启动 Activity 的限制。