Android的任务和回退栈

来源:互联网 发布:我的世界为什么用java 编辑:程序博客网 时间:2024/06/08 22:22

       一个应用通常有多个Activity。每个activity围绕一个特定的功能设计,用户可以操作它并且可以启动其他的activity。举个例子,一个电子邮件应用可能有一个activity去呈现新邮件列表。当用户选择了一封邮件,会打开一个新的activity来呈现邮件内容。


       一个activity可以启动另一个应用的activity。例如,如果你的应用想要发送email,你可以定义一个intent来执行一个发送操作并且携带一些数据:email的地址,消息。一个其他应用的activity需要声明可以处理这类的intent。在这个例子中,intent是要发送一封email,所以一个email应用会启动(如果有多个activity支持同一个intent,系统会让用户选择要使用哪一个)。当email被发送出去,你的activity会恢复,看起来,email activity就是你应用的一部分。为维护这种无缝的用户体验,尽管activity可能来自于不同的应用,android系统依然会将这些activity都保存在同一个任务中。

       一个任务就是用户为了执行特定工作而与之交互的activity的集合。这些activity会根据被打开的顺序被安放在一个栈(回退栈)中。

       设备的主屏幕是大多数任务的启动场所。当用户触摸一个应用图标,该应用的任务就会来到前台。如果该应用当时没有任务,就会创建一个新任务,同时,主activity就会作为这个栈中的根activity被打开。

       当一个activity启动另一个activity时,这个新的activity会被放到栈的顶端并且获得焦点。前一个activity仍然保存在栈中,但已经被停止了。当一个activity停止,系统会保存用户界面的当前状态。当用户按了返回按钮,当前的activity会被弹出栈(activity会被销毁)并且恢复前一个activity(恢复刚被保存的界面状态恢)。在栈中的activity只有在弹出和压入两种操作--被当前activity启动时,压入,用户使用返回按钮离开时,弹出,除此之外,栈中activity位置和顺序都不会发生变化。正应为这样,回退栈的操作符合“后进先出”的原则。下面的图沿着时间线演示了回退栈在不同时刻的进度。

       如果用户继续按返回,那么在栈中所有的activity都会被弹出,直到用户返回到主屏幕(或者到该任务开始的地方)。当所有的activity都从栈中移除后,任务就不复存在了。

       任务是一个紧密结合的单元,当用户开始一项新任务或者回到主屏幕(通过主屏幕按钮)时,它会被移到后台。当任务进入后台,栈中所有的activity都会停止,但是任务的回退栈会保持原封不动--当任务被另一个任务取代时只会简单的失去焦点(如下图所示)。任务可以重回到前台,所以用户可以在哪“丢弃”在哪“捡起”它。举个例子,有三个activity在当前任务(任务A)的栈中--其中两个在当前activity的下面。这时,用户按下Home键回到主屏幕,然后启动了一个新的应用。当显示主屏幕时,任务A进入后台。当新应用启动时,系统为该应用启动了一个新任务(任务B)。当用户与该应用交互完毕之后,重新回到主界面并且选择任务A的应用。这时,任务A回到前台--栈中的三个activity都原封未动并且恢复在栈顶的activity。在这个时候,用户依然可以Home键返回主屏幕,选择任务B的应用图标来切换到任务B(也可以通过最近使用应用列表启动)。这就是android多任务的一个例子。
       注:在后台可以同时存在多个任务。但是,如果用户在运行多个后台任务,系统可能会销毁后台activity来回收内存,导致activity的状态丢失。关于这方面内容后面小节讲述。

       因为在回退栈中的activity从来不会被重排,如果你的应用允许用户从多个activity启动一个特定的activity,那么会新创建该activity的一个实例并且把它放到放到栈顶。因此,在你的应用中一个activity可能被实例化多次,如下图所示。因此,用户使用回退键返回,那么每个activity的实例会按照被打开的反向顺序被显示。但是,如果你不想把一个activity实例化多次,你可以修改这种行为。关于如何修改,我们稍后会在“任务管理”一节中讨论。

让我们来总结一下activity和任务的默认行为:
  • 当Activity A启动Activity B,Activity A会停止,但是系统会保存Activity A的状态(例如滚动条位置,编辑框中的文字等)。如果在Activity B时,玩家按返回键,恢复Activity A。
  • 当用户按下Home键离开一个任务,当前的Activity会被停止并且当前任务会进入后台。系统保存该任务中所有Activity的状态。如果用户通过启动图标再次启动该任务,该任务会回到前台并且恢复栈顶端的Activity。
  • 如果用户按下回退键,当前的Activity会从栈中弹出并且销毁。栈中的前一个Activity被恢复。当一个Activity被销毁时,系统不会保存该Activity的状态。
  • Activity会被实例化多次,即使是由其他任务启动的。


Activity 对象的回退栈
Activity在 启动以后 会存储在一个回退栈中,
栈顶元素为正在运行的activity,
栈底最早启动的那个activity.
一个app进程可能会存在很多这样的回退栈。


Activity 对象的启动模式

Activity在启动时是可以指定启动模式的,一般可以在清单配置文件
中通过修改activity的launchMode属性进行配置,它的值有如下
四种类型:
1)standard(标准模式):每次启动activity都会重新创建一个新的实例。(此模式为默认模式)
2)singleTop(栈顶模式):当此activity已经是栈顶时,再次启动不会创建新的activity.
3)singleTask(单任务模式):一个任务栈中此activity的实例只能有一份,
                        当它不是栈顶时,再次启动它时,位于它上面的activity会销毁。
4)singleInstance(单实例模式):在内存中此activity实例只有一份,且会独享一个任务栈。


Activity 的亲族设置

Activity的亲族设置与启动模式会影响activity在任务栈中的一个存储位置,
亲族设置的配置需要借助activity的taskAffinity属性进行配置。

在android中每个任务栈都有一个亲族值,此值与回退栈的栈底activity的亲族值相同,
每个activity都有亲族值,假如没有配置默认与application对象的亲族值相同,application对
象的亲族值假如没有配置默认与清单配置文件的根元素指定的包名(package)相同。






亲族值一般会与activity的单任务模式和单实例模式一起使用。
(一个界面中取启动 另一个界面,每个界面都可以指定用哪种模式启动,默认是standard标准模式)

一:以singleTask模式启动的activity,在启动前,首先检测内存中有没有相同亲族值的任务栈,
假如没有会创建一个新的任务栈进行存储。
假如有,这个通过singleTask启动的activity去启动其他不是singleInstance模式的activity会与
这个singleTask模式的activity存储在同一个任务栈中。
(也就是说:以singleTask模式启动的界面,去启动另外一个非指定用singleInstance模式启动的
           界面时,首先会判断内存有没有相同的亲族值,没有创建一个新的任务栈,
          有的话,直接存储在 以singleTask模式启动的界面的同一个任务栈中)

二:以singleInstance模式启动的activity,在此界面中去启动其它的activity
    时,这个要被启动的activity存储在哪里取决于有没有相同亲族值的任务栈,
    假如有则直接存储,
    假如没有则会创建一个新的任务栈,再进行存储。


0 0