android启动模式对activity的影响

来源:互联网 发布:高考状元笔记淘宝 编辑:程序博客网 时间:2024/04/28 10:52
首先说明  intent的FLAG和activity在manifest文件中的定义也可以影响activity的行为


1.task:   与Android系统是个多任务的系统中的任务是不同的。后者更倾向于多进程和多线程来说的,而这里的任务与application(应用程序)和activity(活动)有关系. 从activity的角度说,任务就是activity的集合,共同完成一项工作。这些activity排列在一个栈中,这就有了下面的概念,Back栈。
2.Back stack(后退栈):activity按照打开的顺序排列,形成的栈,通常我们也可以说是任务栈。如果用户长时间离开task(比如30分钟),系统会清理这个栈中除了根activity以外的所有activity,当用户再次回来的时候,只有根activity在栈中。


android:launchMode=[“standard” | “singleTop” | “singleTask” | “singleInstance”]
1.默认值是“standard”。

   standard || singleTop
   一个Activity是“standard”或“singleTop”启动模式,可以被实例化多次。一旦有一个新的intent给“standard”activity,一个响应这个intent的新的实例就会被创建。每个实例会处理单独的intent。相似的,一个“singleTop”activity的实例可能也会被创建去处理新的intent。然而,如果目标task已经存在一个此activity的实例在栈顶,这个实例会收到这个新intent(在onNewIntent中回调),新的实例就不会被创建了。
2.  SingleTask  ||  singleInstance
   “singleTask” activity允许其他activity成为task中的一部分 ,并且它通常在task栈的根部,其它activity(必须是“standard”和“singleTop”模式的activity)可以加载到这个栈上。另一方面,“singleInstance”模式的activity不允许任何其它activity加载到这个task栈上。它是这个task中唯一的activity。如果它启动另一个activity,那个activity会被指引到不同的task中,这个行为就像在intent中用FLAG_ACTIVITY_NEW_TASK标记一样。(linc注:通常来说,manifest中用“singleTask”启动模式和在intent中用FLAG_ACTIVITY_NEW_TASK标记的行为是一样的)。

3.Intent中activity相关的6个Flag比较重要:

FLAG_ACTIVITY_NEW_TASK

FLAG_ACTIVITY_SINGLE_TOP

FLAG_ACTIVITY_CLEAR_TASK

FLAG_ACTIVITY_CLEAR_TOP

FLAG_ACTIVITY_NO_HISTORY

FLAG_ACTIVITY_REORDER_TO_FRONT

 

1、  FLAG_ACTIVITY_NEW_TASK

与启动模式中的“singleTask”行为相同。

2、  FLAG_ACTIVITY_SINGLE_TOP

与启动模式中的“singleTop”行为相同。

3、  FLAG_ACTIVITY_CLEAR_TASK

必须要与FLAG_ACTIVITY_NEW_TASK配合使用,这个activity新启动一个栈,原来栈被清空,栈中的activity也被销毁。

4、  FLAG_ACTIVITY_CLEAR_TOP

A B C D四个activity在一个栈中,用此flag启动B,原来的B被唤出来,CD被clear。不能与FLAG_ACTIVITY_SINGLE_TOP同用。可以和FLAG_ACTIVITY_NEW_TASK同用。

5、  FLAG_ACTIVITY_NO_HISTORY

当离开activity并不可见时,此activity会从栈中移除并不留下记录。

6、  FLAG_ACTIVITY_REORDER_TO_FRONT

重新排列栈中activity的顺序。如:栈中有A B C D四个activity,用此flag启动B,原来的B被唤起到栈顶。重新排序后顺序:A C D B



4.Activity的其他属性:

android:allowTaskReparenting=["true" | "false"]

android:alwaysRetainTaskState=["true" | "false"]

android:clearTaskOnLaunch=["true" | "false"]

android:finishOnTaskLaunch=["true" | "false"]

android:noHistory=["true" | "false"]
android:taskAffinity="string"

这些属性都是在Manifest中定义的

1、  先来说说 taskAffinity属性:task的亲属关系,设置的字符串应该是另一个task名,通常情况下是一个application的名称。拥有相同taskAffinity的activity同属于一个task,从用户角度来看是属于同一个应用程序(application)。一个task的亲属关系取决于task的根activity。

它是个很重要的属性,它会配合其他属性和flag共同影响activity的行为。首先它与“singleTask”模式或FLAG_ACTIVITY_NEW_TASK Flag配合,启动后此activity会属于另一个task,task名就是taskAffinity的设置值。其次,它会和allowTaskReparenting属性配合使用,详见allowTaskReparenting。

默认情况下,一个application中的所有activity同属于一个亲属关系。如果想让activity不属于任一个task,那么把taskAffinity的值设为空吧。如果你不设它,那么系统会为你默认为所属application的名称,也就是在manifest中的package名。

 

2、  allowTaskReparenting:与字面理解相同,本属性允许activity重新指定Task。默认值是false。通常情况下我们不设置此属性,activity在生命周期中只属于一个Task。而设置成true后,需要与taskAffinity属性配合使用,当原来的task转到后台,亲属task转到前台,那么此时activity就会属于当前的task。

3、  alwaysRetainTaskState:总是保留task的状态。默认值是false。此时会遵循系统的清理栈的行为。如果设置为true,系统会保留栈中所有activity及其状态,当用户再次回来的时候,发现一切如初。

4、  clearTaskOnLaunch:当再次启动task时,系统会清理掉除了根activity以外的所有activity。默认值是false。

5、  finishOnTaskLaunch:这个属性与上面的clearTaskOnLaunch很像,不过它是指单个activity的,而不是整个栈。当设置为true时,task重启后,这个activity就不显示了。默认值为false。优先级高于allowTaskReparenting。

6、  noHistory:如果设置true,当离开activity并不可见时,此activity会从栈中移除并不留下记录。默认值为false。与上面FLAG_ACTIVITY_NO_HISTORY行为相同。


   

最近一直在被activity之间传值问题所纠结,然后我所要求是不是简单的传值,它们包括应用间的传值与应用内的传值,并且加上了activity的加载模式,这个就有点不一样了。那今天就以android里activity的四种加载模式为话题说说吧。

  总所周知,activity有四种加载模式:standard,singleTop,singleTask,singleInstance。standard模式也就是标准模式,是activity默认的模式,这个比较简单,就不讲。下面主要就说说其它三种。

   singleTop
  我觉得学习它得跟standard一起。他们唯一的却别就是,当一个启动目标为singleTop模式的activity已经有实例在当前Task栈顶的时候,activity不会重新实例化,而是使用在Task栈顶的那个activity(具体的过程:onResume->onNewIntent->onResume).

  测试(由于情况太多,代码却简单,代码就不贴了,都是直接打log的事情):

  第一种情况:应用里调用

  A(main+launcher),B(singleTop) : A->B--startActivity-->B   同个Task,不重新生成一个B的实例

  A(main+launcher),B(singleTop) : A->B--startActivityForResult-->B   同个Task, 会重新生成一个B的实例

  第二种情况:应用间调用

  A1(main+launcher),A2(main+launcher+singleTop) : A1->A2--startActivity-->A2   同个Task,不重新生成一个A2的实例  

  A1(main+launcher),A2(main+launcher+singleTop) : A1->A2--startActivity-->A2   同个Task,会重新生成一个A2的实例

  看来,SingleTop模式似乎与启动方式有关,与是否是应用间调用没有关系:当以startActivityForResult方式启动时候,跟standard模式一模一样。

  singleTask
  它跟后面说的singleInstance一起学。他们的唯一却别就是:singleInstance模式的activity且只能存在一个单独的Task,且这个Task之鞥有且仅有它本身一个activity;而singleTask没有这个要求(即含有singleTask-activity的Task可以含有很多activity)。singleTask意思就是说:这个activity只能有一个实例,只能存在一个Task。官方上说:The system creates a new task and instantiates the activity at the root of the new task. However, if an instance of the activity already exists in a separate task, the system routes the intent to the existing instance through a call to its onNewIntent() method, rather than creating a new instance. Only one instance of the activity can exist at a time.  Although the activity starts in a new task, the BACK key still returns the user to the previous activity.我感觉没有说清楚,我们暂且不管,先测试:

  第一种情况:应用里调用

  A(main+launcher),B(singleTask),C : A-startActivity->B->startActivityForResult->C-startActivity->B   同个Task,不会重新生成B实例,C销毁。

  A(main+launcher),B(singleTask),C : A-startActivityForResult->B-startActivityForResult->C-startActivityForResult->B   同个Task,不会重新生成B实例,C销毁。第1、3个startActivityForResult无法返回数据

  数据如下:图片中的数据均是主界面TaskActivity开始截图的,上为

android启动模式对activity的影响

第二种情况:应用间调用

  A1(main+launcher),A2(main+launcher+singleTask) : A1-startActivity->A2-startActivity->A2   不同Task,不会重新生成A2

  A1(main+launcher),A2(main+launcher+singleTask) : A1-startActivityForResult->A2-startActivityForResult->A2 不同Task,不会重新生成A2,第1,2个startActivityForResult失效

  看来,应用里调用singleTask模式的activity时候,不会产生新的Task,而应用间调用singleTask模式的activity时候,会产生新的Task。另外startActivityForResult函数对启动singleTask模式的activity会失效。另外,当重用前面的singleTask模式的activity时,该Task栈中间的activity会被销毁。

  singleInstance
  上面说了,这里就不讲了。测试结果就是:除了在应用里调用时为都不同Task,其它的都一样。