什么是Activity的启动模式?当启动一个Activity的时候,系统会创建一个实例,并把它放入到一个任务栈中,至于如何存放,就是由这个启动模式来决定的。Android系统支持多任务,所以系统中会同时存在多个任务,而一个App中的组件可能存在于不同的任务栈中,甚至一个App的某个activity可以单独存在于独立的一个任务栈,并且一个任务栈中也可能存在来自不同App的activity实例。
Activity的LaunchMode有四种启动方式:standard、singleTop、singleTask、singleInstance,他们的具体含义如下:
(1)standard:默认的启动模式,每次启动都会去创建新的Activity实例,并且有完整的生命周期回调,在这种模式下,新启动的activity会存在于启动它的那个activity的栈中。由于这个特性,会引发一个问题,当我们尝试使用ApplicationContext来启动使用了standard模式的activity时,会出现如下错误:
E/AndroidRuntime(3403): android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
这是因为ApplicationContext是非activity类型的context,它没有任务栈,导致新启动的activity“无家可归”,解决办法就是将要启动的activity设置为FLAG_ACTIVITY_NEW_TASK模式,让它在启动的时候创建一个新的任务栈。
(2)singleTop:栈顶复用模式,这种模式下,如果新的activity已经在当前栈顶存在实例,则此activity不会重新创建,转而会回调它的onNewIntent方法,这个回调方法会携带Intent参数,可以用来获取传递的参数。此时因为没有创建新的实例,所以onCreat和onStart并不会回到,如果当前栈内已存在有此activity的实例,但是不位于栈顶,新的实例仍然会被创建。
(3)singleTask:栈内复用模式。这种模式只要栈内存在待启动activity实例,就不会重新创建实例,与singleTop一样,只会回调OnNewIntent方法,并通过把栈内实例顶部的其他实例全部出栈,来让新的activity实例处于栈顶。
(4)singleInstance:单实例模式,这可以看成是加强版的singleTask模式,因为使用这种模式的activity,会启动在单独的一个栈中。
想要给activity知道启动模式有两种方法,第一种是在AndroidMenifest.xml文件中给activity设置 android:launchMode="singleTask"
另一种情况就是通过Intent中设置标志位来指定intent.addFlages(Intent.FLAG_ACTIVITY_NEW_TASK)
,这两种方式是有区别的,第一,优先级不同,第二种模式比第一种模式优先级高,即当两种方法同时使用时,以第二种为准;第二,限定范围不同,第一种无法为activity设定FLAG_ACTIVITY_CLEAR_TOP标识,第二种无法指定为singleInstance模式。
上面说到activity的Flags即标志位,标志位的作用有很多,可以设定activity的启动模式,决定activity的运行状态等。下面记录几个常用的标志位:
-
FLAG_ACTIVITY_NEW_TASK
这个标志位的作用就是指定activity为“singleTask"模式。
-
FLAG_ACTIVITY_SINGLE_TOP
这个标志位的作用就是指定activity为“singleTop"模式。
-
FLAG_ACTIVITY_CLEAR_TOP
这个标志位的作用就是当栈中存在有待启动的activity的实例时,会清空该实例顶部使得待启动activity处于栈顶位置。
-
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 该标志使得启动的activity不会出现在activity历史列表当中。