任务和返回栈
使用android:launchMode="standard|singleInstance|single Task|singleTop"来控制Acivity任务栈。
任务栈是一种后进先出的结构。位于栈顶的Activity处于焦点状态,当按下back按钮的时候,栈内的Activity会一个一个的出栈,并且调用其onDestory()方法。如果栈内没有Activity,那么系统就会回收这个栈,每个APP默认只有一个栈,以APP的包名来命名.
任务是指在执行特定作业时与用户交互的一系列 Activity。 这些 Activity 按照各自的打开顺序排列在堆栈(即返回栈)中。
例如:你在主屏幕中打开一个应用,其实就是开启了一个activity,然后又由这个activity开启了一系列其他的activity,这些activity可能属于同一个应用也可能属于不同的应用。但只要是在这一系列的操作中打开的activity,他们就都处于同一个Task(任务)当中。
设备的主屏幕是大多数任务的起点.当用户触摸应用启动器中的图标时,该应用的任务将出现在前台。 如果应用不存在任务(应用最近未曾使用),则会创建一个新任务,并且该应用的“主”Activity 将作为堆栈中的根 Activity 打开。
前台activity:当activity启动另一个activity时,该新 Activity 会被推送到堆栈顶部,成为焦点所在(前台activity)。当按下back键时,系统会将栈顶的activity销毁,恢复前一个activity。
任务是一个有机整体,当用户开始新任务或通过“主页”按钮转到主屏幕时,可以移动到“后台”,变成后台任务。后台任务中的activity全部停止,但其返回栈中activity的顺序不变。(返回栈中的activity顺序永远不变)。也就是说,当另一个任务发生时,该任务仅仅失去焦点而已。
Activity 和任务的默认行为总结如下:
- 当 Activity A 启动 Activity B 时,Activity A 将会停止,但系统会保留其状态(例如,滚动位置和已输入表单中的文本)。如果用户在处于 Activity B 时按“返回”按钮,则 Activity A 将恢复其状态,继续执行。
- 用户通过按“主页”按钮离开任务时,当前 Activity 将停止且其任务会进入后台。 系统将保留任务中每个 Activity 的状态。如果用户稍后通过选择开始任务的启动器图标来恢复任务,则任务将出现在前台并恢复执行堆栈顶部的 Activity。
- 如果用户按“返回”按钮,则当前 Activity 会从堆栈弹出并被销毁。 堆栈中的前一个 Activity 恢复执行。销毁 Activity 时,系统不会保留该 Activity 的状态。
- 即使来自其他任务,Activity 也可以多次实例化。
四种LaunchMode:
- standard:默认。系统在启动 Activity 的任务中创建 Activity 的新实例并向其传送 Intent。Activity 可以多次实例化,而每个实例均可属于不同的任务,并且一个任务可以拥有多个实例。
- singleTop:如果当前任务的顶部已存在 Activity 的一个实例,则系统会通过调用该实例的 onNewIntent() 方法向其传送 Intent,而不是创建 Activity 的新实例。Activity 可以多次实例化,而每个实例均可属于不同的任务,并且一个任务可以拥有多个实例(但前提是位于返回栈顶部的 Activity 并不是 Activity 的现有实例)。**例如,假设任务的返回栈包含根 Activity A 以及 Activity B、C 和位于顶部的 D(堆栈是 A-B-C-D;D 位于顶部)。收到针对 D 类 Activity 的 Intent。如果 D 具有默认的 "standard" 启动模式,则会启动该类的新实例,且堆栈会变成 A-B-C-D-D。但是,如果 D 的启动模式是 "singleTop",则 D 的现有实例会通过 onNewIntent()接收 Intent,因为它位于堆栈的顶部;而堆栈仍为 A-B-C-D。但是,如果收到针对 B 类 Activity 的 Intent,则会向堆栈添加 B 的新实例,即便其启动模式为 "singleTop"也是如此。
- singleTask:系统创建新任务并实例化位于新任务底部的 Activity。但是,如果该 Activity 的一个实例已存在于一个单独的任务中,则系统会通过调用现有实例的onNewIntent()方法向其传送 Intent,而不是创建新实例。一次只能存在 Activity 的一个实例。
- singleInstance:与 "singleTask" 相同,只是系统不会将任何其他 Activity 启动到包含启动模式为singleInstance的实例的任务中。该 Activity 始终是其任务唯一仅有的成员;由此 Activity 启动的任何 Activity 均在单独的任务中打开。
示例
我们再来看另一示例,Android 浏览器应用声明网络浏览器 Activity 应始终在其自己的任务中打开(通过在 <activity>元素中指定 singleTask启动模式)。这意味着,如果您的应用发出打开 Android 浏览器的 Intent,则其 Activity 与您的应用位于不同的任务中。相反,系统会为浏览器启动新任务,或者如果浏览器已有任务正在后台运行,则会将该任务上移一层以处理新 Intent。
无论 Activity 是在新任务中启动,还是在与启动 Activity 相同的任务中启动,用户按“返回”按钮始终会转到前一个 Activity(始终记住这个逻辑,系统严格按照这个逻辑来执行)。 但是,如果启动指定 singleTask 启动模式的 Activity,则当某后台任务中存在该 Activity 的实例时,整个任务都会转移到前台。此时,返回栈包括上移到堆栈顶部的任务中的所有 Activity。