Android Tasks and Back Stack
每一个Android应用都由多个activities组成,每一个Activity可以执行特定的action也可以打开其他的activity。举例说明,一个Email应用会有一个Activity来显示未读邮件列表,当用户点击其中一封邮件时,一个用来显示这封邮件内容的Activity就会被创建出来。
Activity甚至可以启动本机上其他应用的Activity。比如说,当你的应用要发送邮件时,你可以定义一个包含邮件地址征文等信息和发送消息action的Intent。与此同时另外一个应用的Activity被声明为可以执行这个Intent然后打开它。在这个过程中,Intent被定义为发送邮件,所以一个Email应用会启动并创建“写邮件”Activity,(当然,如果系统中包含多个可以支持此Intent的Activity,系统会弹出一个列表来供你选择)。当Email被发送出去后,启动这个Intent目标的Activity会被恢复,这就好像是发送Email的Activity是应用自身的一部分一样。通过将两个来自于不同的应用Activity放入同一个Task,Android完美实现了用户操作的无缝衔接。
回到主题,Task是为了完成用户某项任务的Activity集合。在这个集合中,Activity按照被打开的先后顺序存放在栈中。
设备主屏是大多数Task的起点。当用户点击启动器上的App图标或者App快捷方式图标时,这个应用的Task会被加载到前台。如果最近这个应用没有被启动,新的Task会被创建并将声明为"main"的Activity作为根Activity打开,添加到栈中。
如果此时Activity A去启动Activity B,Activity B会被压入栈顶并获得焦点。Activity A依然保持在栈中,但是已被中止(当一个Activity被中止时,系统只保留了当前UI的状态数据),当用户按下返回键时,Activity B会从栈顶推出(彻底被销毁),Activity A会被恢复(之前的UI状态资源会被还原),栈中Activity排序顺序是始终不变的,当Activity启动时被压入,用户按下返回键时被推出。这一操作遵循“后进先出”的原则。下图展示了每次操作时栈的状态。
如果用户一直按返回键的话,每一个Activity都会被推出栈直到返回到设备主屏。当所有Activity被从栈中移除时,Task也就随之消失了。
当用户开启一个新的Task或者是直接回到主屏,当前的Task就会被置入后台。Task中的所有Activity都被中止,但栈依然有效,只不过是焦点被其他Task把持着罢了。如下图所示。
用户从离开Task的位置返回时,后台的Task会被置前。举例说明,Task A中包含三个Activity(按照Task 栈的定义,当前运行的Activity位于栈顶,其他两个Activity位于当前Activity下面),假设用户此时回到主屏并从启动器中启动另外一个应用,主屏出现之后Task A就会被置入后台,新的应用启动后Android会为这个应用创建新的Task B来放置属于它的Activity,用户操作完Task B应用后再次切回主屏,选择启动Task A应用时Task A就会回到前台,在栈中的三个Activity会如前所述,栈顶的Activity被恢复,其他两个Activity仅保留状态资源置于顶部Activity下面。当然了,用户此时也可以通过回到主屏或者是点击“最近使用的应用”来切换到Task B。
注意:在Android系统可以同时存留多个后台任务,但是如果系统如果需要回收内存时就可能会销毁掉栈中的Activity,这就会导致Activity状态的丢失。详见 Activity state.
由于栈中的Activity从来不会被重新排列,你的应用如果允许从多个Activity中去启动某一特定Activity,特定的Activity在每一次启动时都会被实例化压入栈中而不是将之前已经实例化的Activity置入栈顶。这样的话,每一个实例化的Activity都拥有独立的UI状态资源,当用户按下返回键时按照栈中Activity顺序依次被推出。当然你也可以修改这些Activity的属性来满足你仅有一个特定Activity实例存在的要求。详见 Managing Tasks.
小结:
- 从Activity A启动Activity B,Activity A会被中止,但系统会保留它的UI状态资源(比如滚动位置、表单数据),如果用户在Activity B状态时按下返回键,Activity A就会被恢复到原始状态。
- 当用户从当前应用按下Home键时,当前Activity被中止,所属的Task被置入后台。系统会保留Task中所有Activity的状态资源. 用户再点击开始当前Task的应用图标时,Task会被前置并且恢复栈顶的Activity。
- 如果用户按下返回键,当前的Activity会被从栈中推出销毁,栈中下一Activity会被恢复。一个Activity被销毁时,系统就不会再保留它的状态资源。
- Activitiy可以被实例化多次,当然在不同的Task中也是适用的。