一直以来 Activity 和 Task 的关系就不是很清楚。即使在前公司修改 framework 时,因为分工也很少接触 Activity 相关的东西,而且就遇到的问题而言,Activity 这块也很少碰到 bug,基本算是个完成度和可靠性相当高的模块,定制 framework 也很少碰它,毕竟就操作系统而言这属于任务调度,这里出了问题那 os 基本也就挂了,核心模块之一。
现在工作接触的 app 开发比较多,所以有必要梳理一下,刷文档的同时随手记录一下。可能有遗漏的知识点,以后遇到问题了再补。
基本关系
- 启动的 Activity 会被压到当前任务栈(Task back stack)里,每一个 Activity 必然属于一个栈,栈里所有的 Activity 构成一个 task。新的 Activity 会默认被压到栈顶。栈嘛,LIFO。
- 当按下 back 按钮时,顶上的会被弹出。当最后一个 Activity 被弹出后,task 就不复存在了。
- 当按下 home 按钮时,当前 Activity 被切到 stop 状态,它所在的 task 被切到后台;当用户通过多任务按钮切换回当前 Activity 时,task 被切换回前台,并且栈顶的 Activity 回到 resume 状态。
- 一个 Actvity (根据 intent 的 flag 或者在 manifest 文件里的配置)可能会被初始化多次到不同的 task 里。
Task 管理
- 在多 Window 的系统(7.0+),每个 window 有自己的 tasks。
- 当 manifest 和 startActivity 的 Intent 里同时有对目标 Activity 的配置时,Intent 的配置项生效。
- manifest 和 Intent 对 task 的配置并不一一对应,各有自己特有的项目。
在 manifeset 文件里关于 task 的可配置项有:
- taskAffinity:用于协同 Activity。调度时会先考虑把目标 Activity 移动到相同 affinity 的 Activity 所在的 task 里。
- launchMode:如何加载目标 Activity 到 task 里。
- standard 默认形式,加载到当前 task,并且该 Activity 可被初始化多次,不管是初始化到当前 task 还是到其它 task。
- singleTop 当前 task 的栈顶是目标 Activity 时,该 Activity 将收到 onNewIntent,并且不会被创建新实例;当目标 Activity 不在栈顶或者没有被实例过,那就初始化该 Activity 并压到栈顶。该 Activity 可以被实例化多个,并且可能属于不同的 task,也可能属于当前 task(前提是不在当前 task 栈顶)。
- singleTask 目标 Activity 有且只有一个实例。如果已经被初始化过,则收到 onNewIntent,否则创建一个新的实例并创建一个新的 task。
- singleInstance 目标 Activity 有且只有一个实例,并且所属 task 也只有目标 Activity 一个 Activity,其它任何由该 Activity 启动的 Activity 都将被压到别的栈里去。
- allowTaskReparenting:和 taskAffinity 类似,协同 Activity 之用。当为
true
时会结合其它配置项,如 affinity,来调整目标 Activity 所在的 task。 - clearTaskOnLaunch
- alwaysRetainTaskState
- finishOnTaskLaunch
Intent flag 里关于 task 的可配置项有:
- FLAG_ACTIVITY_NEW_TASK 和 launchMode = singleTask 一毛一样。
- FLAG_ACTIVITY_CLEAR_TOP 【Intent flag 限定!!】嘛,就是当目标 Activity 实例已经存在在其它 task 里时,把该 task 里目标 Activity 头上的 Activity 全部弹出销毁,然后调用目标 Activity 的 onNewIntent。
- FLAG_ACTIVITY_SINGLE_TOP 和 launchMode = singleTop 一毛一样。