安卓Task和Back Stack

概述

一个Activity允许用户完成一些操作,甚至,Android中设计Activity为组件的形式,这样,多个Activity——甚至是其它App的Activity可以一起完成一项任务。

Task

多个Activity一起完成一项工作时,它们的集合被称作一个Task。
A task is a collection of activities that users interact with when performing a certain job.

Back Stack

一个Task所有的Activity被放置在一个stack结构中,根据它们的启动顺序被添加。
stack不会进行重新排列,只会在打开新Activity时添加其到栈顶,或finish时从栈顶移除。所以Activity在此stack中表现为"last in, first out"。

因为上述特点,多个Activity在打开和关闭时,stack表现出“回退栈”这样的效果。

Task的底层实现

系统中,每一个Activity组件实例被使用一个ActivityRecord对像表示,所有的Activity组件都保存在一个ActivityStack对象的字段ArrayList mHistory中。
ActivityRecord.task字段表示其所在Task,类型是TaskRecord。
假设把所有Activities指定编号:a0,a1,a2...an,表示mHistory中第0,1,2...n个Activity,那么,Task就是从a0到an中连续的一个个“子序列”,一个Task包括1或多个Activity。
可见:Task中的Activity的“栈结构”是通过ArrayList间接实现的

在启动一个Activity时,可以在Intent中添加标记,指示其运行在新的Task中,还是已经存在的Task中。

若为Activity指定为NEW_TASK,那么它被添加到mHistory的末尾,并且作为新Task的栈底的Activity—— root activity。

若启动的Activity运行在已有的Task中,此时:
对mHistory进行倒序遍历,找到task和对应newActivity一致的ActivityRecord record对像,然后添加其到此record后面。

前台和后台Task

当一个Activity中栈顶Activity正在显示时,它就是前台Task。
栈顶topActivity转为stopped状态时Task也变为后台的。
一个Activity总是属于某个Task,它的Resumed或Stopped状态影响其Task状态。

每次Task栈顶的Activity被finish,那么它出栈。新的栈顶的Activity被resume。
若所有Activity都finish并出栈,此Task不再存在,之前启动此Task时的前台Task被转到前台。

Activity和Task默认的表现是:

  • When Activity A starts Activity B, Activity A is stopped, but the system retains its state (such as scroll position and text entered into forms). If the user presses the Back button while in Activity B, Activity A resumes with its state restored.

  • When the user leaves a task by pressing the Home button, the current activity is stopped and its task goes into the background. The system retains the state of every activity in the task. If the user later resumes the task by selecting the launcher icon that began the task, the task comes to the foreground and resumes the activity at the top of the stack.

  • If the user presses the Back button, the current activity is popped from the stack and destroyed. The previous activity in the stack is resumed. When an activity is destroyed, the system does not retain the activity's state.

  • Activities can be instantiated multiple times, even from other tasks.

Activity的状态保存

处于stopped状态的Activity,它的内存状态和Resumed比并没有变化。这样稍后用户回到界面时可以从Stopped状态转为Resumed状态,即从后台转到前台。

不过系统为了内存利用,可能回收长期处于后台的Activity,这样,
用户再回到界面时,Activity会重新创建,未保存的状态会丢失。
为了之后用户回到当前Task时继续原先的操作,需要主动保存view和activity对象的一些状态。
通过:
onSaveInstanceState(Bundle outState)
onRestoreInstanceState(Bundle savedInstanceState)
onCreate(Bundle savedInstanceState)

管理Task

可以通过manifest文件中配置标签或设置startActivity()参数intent中的flags的方式改变Activity和启动它的Task的从属关系,以及在Back Stack中的行为表现。

attribute有:

taskAffinity
launchMode
allowTaskReparenting
clearTaskOnLaunch
alwaysRetainTaskState
finishOnTaskLaunch

flag有:

FLAG_ACTIVITY_NEW_TASK
FLAG_ACTIVITY_CLEAR_TOP
FLAG_ACTIVITY_SINGLE_TOP

Activity的启动模式

可以通过配置或设置intent的flags来定义要启动Activity的方式。
即和当前Task的关系。
一些模式只有flags中可以配置,一些只有manifest中设置。
如果同时以flags和manifest的方式设置了启动模式,那么flags中的设置优先。

使用manifest

使用launchModeattribute。

"standard" (the default mode)

Default. The system creates a new instance of the activity in the task from which it was started and routes the intent to it. The activity can be instantiated multiple times, each instance can belong to different tasks, and one task can have multiple instances.

singleTop

如果当前Task栈顶是对应Activity类的实例,则将intent传递给它的onNewIntent()方法,不创建新实例。

特点:一个Task中可以存在多个,多个实例可以存在于不同Task中。

singleTask

若当前Task或其它Task中存在要启动的Activity的实例,就发送intent给它,并且设置了flag:Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT。已有的Activity的onNewIntent()被执行,位于其上的stack中的其它Activity都会被finish,只留下此rootActivity被resume。

若系统中还不存在Activity实例,就创建一个新Task,并且将此Activity作为其root activity。此时,若finish此实例,将回到启动它时的前一个Activity。

特点:只能有一个。

singleInstance

Same as "singleTask", except that the system doesn't launch any other activities into the task holding the instance. The activity is always the single and only member of its task; any activities started by this one open in a separate task.

特点:只能有一个,且其Task只包含此Activity。

返回规则

不论启动的Activity在当前Task还是新的Task中,返回按钮总是把用户带到前一个Activity界面。

若启动singleTask的Activity在其它Task2中,那么其中的Activity都会被添加到当前Task的返回路径的前面,所以仅在用户关闭对应Task2中的所有Activity后,才返回到当前启动操作时的Task1。

diagram_backstack_singletask_multiactivity

A representation of how an activity with launch mode "singleTask" is added to the back stack. If the activity is already a part of a background task with its own back stack, then the entire back stack also comes forward, on top of the current task.

使用Intent flags

FLAG_ACTIVITY_NEW_TASK

和 "singleTask" 的行为一样。

FLAG_ACTIVITY_SINGLE_TOP

和"singleTop"一样。

FLAG_ACTIVITY_CLEAR_TOP

If the activity being started is already running in the current task, then instead of launching a new instance of that activity, all of the other activities on top of it are destroyed and this intent is delivered to the resumed instance of the activity (now on top), through onNewIntent()).

There is no value for the launchMode attribute that produces this behavior.

FLAG_ACTIVITY_CLEAR_TOP is most often used in conjunction with FLAG_ACTIVITY_NEW_TASK. When used together, these flags are a way of locating an existing activity in another task and putting it in a position where it can respond to the intent.

Note: If the launch mode of the designated activity is "standard", it too is removed from the stack and a new instance is launched in its place to handle the incoming intent. That's because a new instance is always created for a new intent when the launch mode is "standard".

官方文档乱写?

使用affinities

The affinity indicates which task an activity prefers to belong to.
默认的每个activity的affinity是其包名。
可以使用android:taskAffinity改变application或某个activity的taskAffinity。

使用taskAffinity用途一般是:

  • 结合FLAG_ACTIVITY_NEW_TASK
    此时系统寻找affinity 相同的 的Task来放置Activity,如果没有就创建新的Task,此Activity作为其root。
    一个Task的root activity的affinity就是此Task的affinity。

  • 标签属性 allowTaskReparenting为true
    In this case, the activity can move from the task it starts to the task it has an affinity for, when that task comes to the foreground.

清空back stack

默认情况下,系统会保持Task中的stack,即便对应Activity的进程被回收,它还会重建。
若较长时间再回到当前Task,系统会选择清除root外的所有Activity。

可以通过对Activity设置标签属性定制行为:

  • alwaysRetainTaskState
    为root activity设置,无论多久都不会清除任何activity。

  • clearTaskOnLaunch
    为root activity设置,一旦用户离开当前Task,再回来时总是只剩下root。

  • finishOnTaskLaunch
    针对某个activity,包括root,一旦离开再返回Task,设置此属性的activity一定会移除。

入口Task

入口Activity所在的Task一般认为是application的main Task。
当app启动后,点击桌面的icon可以在任何时候返回到main Task。

(本文使用Atom编写)

posted @ 2017-01-13 15:55  everhad  阅读(399)  评论(0编辑  收藏  举报