Activity and Task
一、Activity的生命周期
1、启动activity至用户可见:onCreate->onStart->onResume
2、在activityOne中启动activityTwo:onPause->(onCreate->onStart->onResume)->onStop
注:红色部分为activityTwo的生命周期,外面的为activityOne的生命周期。
3、activityOne和activityTwo都已经加入任务栈中activityOne->activityTwo,用户按回退按钮activityTwo退出,activityOne显示:onPause->(onRestart->onStart->onResume)->onStop->onDestroy
注:红色部分为activityTwo的生命周期,外面的为activityOne的生命周期。
二、LuanchMode(启动模式)
1、standard(activity默认启动模式):当activity设置了standard启动模式,activity都会生成一个新实例添加到任务栈的顶部。无论任务栈的顶部是否为该启动的activity实例,都会生成一个新实例添加到任务栈的顶部。一个任务栈中可以存在多个activity的实例或者多个activity的实例可以存在多个任务栈中。
如:①、栈为 A-B-C-D,D为栈顶,以standard模式启动D以后,此时栈变为:A-B-C-D-D;
②、栈为 A-B-C-D,D为栈顶,以standard模式启动B以后,此时栈变为:A-B-C-D-B;
2、singleTop:当activity设置了singleTop启动模式,如果任务栈的顶部为该启动的activity实例,就不重新生成一个实例添加到任务栈的顶部,而是直接调用该实例的newIntent()方法;如果任务栈的顶部不是该启动的activity实例,就生成一个新实例添加到任务栈的顶部。一个任务栈中可以存在多个activity的实例或者多个activity的实例可以存在多个任务栈中。
如:①、栈为 A-B-C-D,D为栈顶,以singleTop模式启动D以后,此时栈变为:A-B-C-D;
此时activity的回调方法为(都为D的回调方法):onPause->onResume。
②、栈为 A-B-C-D,D为栈顶,以singleTop模式启动B以后,此时栈变为:A-B-C-D-B;
此时activity的回调方法为:onPause->(onCreate->onStart->onResume)->onStop
注:红色部分为B的生命周期,外面的为D的生命周期
3、singleTask:当activity设置了singleTask启动模,系统会检查该activity是否存在一个单独的任务栈中,如果存在就直接调用该实例的newIntent()方法,如果不存在,就重新生成一个任务栈且生成一个新的activity实例放在该任务栈底部。每次只能有一个activity实例的存在;虽然activity生成在一个新的任务栈中,但是通过回退按钮还是能够回到之前的显示的activity界面。
如:①、任务栈1为A-B,B获得用户焦点即为栈顶元素,以singleTask模式启动A以后,
此时activity的回调方法为:onPause->( onRestart ->onStart->onResume)->onStop->onDestroy。
注:红色部分为A的生命周期,外面的为B的生命周期
②、任务栈1为A, A获得用户焦点,以singleTask模式启动A以后,
此时activity的回调方法为(都为A的回调方法):onPause->onResume。
③、任务栈1为A, A获得用户焦点,以singleTask模式启动B以后,
此时activity的回调方法为:onPause->(onCreate->onStart->onResume)->onStop
注:红色部分为B的生命周期,外面的为A的生命周期
4、singleInstance:当activity设置了singleInstance启动模式,系统会检查该activity是否存在一个单独的任务栈中,如果存在就直接调用该实例的newIntent()方法,如果不存在,就重新生成一个任务栈且生成一个新的activity实例放在该任务栈底部。每一个任务栈只能存在一个activity的实例;每次只能有一个activity实例的存在,虽然activity生成在一个新的任务栈中,但是通过回退按钮还是能够回到之前的显示的activity界面。
如:①、任务栈1为A, A获得用户焦点,以singleInstance模式启动A以后,
此时activity的回调方法为(都为A的回调方法):onPause->onResume。
②、任务栈1为A,任务栈2为B,B获得用户焦点,以singleInstance模式启动A以后,
此时activity的回调方法为:onPause->( onRestart ->onStart->onResume)->onStop。
注:红色部分为A的生命周期,外面的为B的生命周期
③、任务栈1为A, A获得用户焦点,以singleInstance模式启动B以后,
此时activity的回调方法为:onPause->(onCreate->onStart->onResume)->onStop
注:红色部分为B的生命周期,外面的为A的生命周期
总结:standard和singleTop相似,唯一的区别就是activity以singleTop模式启动的时候都会检查任务栈顶是否为当前启动activity的实例,而standard就不会去检查直接生产activity的新实例添加到任务栈顶;singleTask和singleInstance相似,唯一的区别就是activity以singleInstance模式启动的时候,每一个任务栈中只能存在一个activity的实例,而singleTask可以存在多个activity的实例。
三、Intent的Flag启动
1、FLAG_ACTIVITY_NEW_TASK: 创建一个新的任务栈启动activity的实例,如果该启动的activity已经在一个任务栈中存在,则任务栈以最后保存的状态回到前台且调用该activity实例的newIntent()方法进行界面显示。和LuanchMode中的singleTask启动模式行为一样。
2、FLAG_ACTIVITY_SINGLE_TOP: 如果启动的activity是当前的activity且在任务栈栈顶(当前显示的activity),就调用该activity实例的newIntent()方法,而不去创建一个新实例。和LuanchMode中的singleTop启动模式行为一样。
3、FLAG_ACTIVITY_CLEAR_TOP: 如果启动的activity已经存在当前任务栈中,就不需要生产一个新的activity实例添加到当前任务栈中,但是需要将当前任务栈中该activity上面的所有的activity都注销掉,只剩下当前启动的activity的实例,然后调用该activity实例的newIntent()方法。
注:FLAG_ACTIVITY_CLEAR_TOP和FLAG_ACTIVITY_NEW_TASK通常一起使用,通过这种方式来定位已经存在其他任务栈中的activity并把该activity放到一个可以进行响应Intent的位置。
四、清除回退栈(Clear the back stack)
用户长时间离开一个任务栈,系统默认会将清除任务栈中除根部以外的所有activity,当用户再次返回任务栈时只有根部的activity能够恢复显示。系统执行这样的行为操作是因为在很长时间之后,用户基本上都会抛弃之前的他们所做的一些操作,而返回任务去进行一些新的操作。
1、alwaysRetainTaskState:如果将任务栈根部activity的alwaysRetainTaskState属性值设置为true,系统将不会执行默认的操作,即使用户长时间离开了任务栈,任务栈仍然保持栈中所有activity的状态。
2、clearTaskOnLaunch:如果将任务栈根部activity的clearTaskOnLaunch属性值设置为true,在任何时候用户离开任务栈并返回,任务栈中的activity都会清除任务栈中除根部以外的所有activity,实际上和alwaysRetainTaskState是相反的。即使用户离开任务栈片刻时间,用户也总是以初始的任务状态返回。
3、finishOnTaskLaunch:这个属性和clearTaskOnLaunch属性很相似,但是它只操作单个的activity,而不是整个任务栈,它能使所有的activity包括任务栈根部的activity都会被清除。如果设置activity的finishOnTaskLaunch属性值设置为true,该activity只会保持在当前任务栈中的状态,如果用户离开并返回任务栈,该activity将不复存在。
五、TaskAffinity(任务密切关系)
这种affinity象征着activity将属于哪个任务,一般的来自同一个应用的所有的activity互相都有着一个affinity,故这些activity一般都放在同一个任务栈中。因而也可以修改每一个activity默认的affinity,定义在不同应用中的activity可以分享同一个affinity或者定义在同一个应用中的activity可以分配不同的任务affinity。
修改manifest.xml中<activity>元素的taskAffinity属性值即可修改每一个activity的affinity。taskAffinity属性值是一个字符串类型的数据,在<manifest>元素中必须声明成默认的包名且必须是唯一的,系统将用这个名字来区分不同应用之间默认任务affinity。
affinity在下面两种情况下面起作用:
① 、当Intent启动activity包含了FLAG_ACTIVITY_NEW_TASK标签。
在这种情况下,通常都会为activity创建一个新的任务栈,然后将activity的实例放到任务栈中;但是如果存在一个任务栈且任务栈的affinity的值和新启动的activity的affinity相同,则将这个activity添加到该任务栈中,否则新建一个任务栈。
② 、当activity设置allowTaskReparenting的属性为true。
在这种情况下,当一个任务栈1进入前台进行显示,其后台任务栈2中的activity的affinity值和任务栈1的affinity值相同,则该activity将移动到任务栈1中。
例如:如果一个e-mail信息应用包含一个访问网页的链接,当点击这个链接就会启动一个activity显示页面,而这个activity是浏览器应用中一个(即具有相同的affinity),但是这个activity被作为e-mail任务栈的一部分。而当浏览器应用启动,浏览器的任务栈进入前台,该activity就会移动到该浏览器任务栈中被显示出来,而当下次e-mail任务栈进入前台,该activity已经不存在该e-mail任务栈中。
六、启动任务
1、如果一个应用程序入口activity的启动模式为standard或singleTop,之后无论用户怎么操作,以何种模式启动其他的activity,当用户按下Home键,当前应用的任务栈将进入后台,一段时间之后用户通过应用图标再次进入应用时(前提是应用没有被系统处理过),应用将会呈现出用户最后一次离开应用的状态。在这种模式下,希望用户按了Home键之后再次进入应用呈现的是入口activity的显示界面状态,则需要将<activity>元素的属性finishOnTaskLaunch值设置为true。
2、如果一个应用程序入口activity的启动模式为singleTask或singleInstance,之后用户进行一些相关的操作,当用户按下Home键之后再通过应用图标进入应用时,应用只会呈现入口activity的显示界面状态。