Activity的生命周期
Activity的启动模式
(1) standard:标准模式
这也是系统的默认模式。每次启动一个Activity都会重新创建一个新的实例,不管这个实例是否已经存在。被创建的实例的生命周期符合典型情况下Activity的生命周期,如上节描述,它的onCreate, onStart,onResume都会被调用。这是一种典型的多实例实现,一个任务栈中可以有多个实例,每个实例也可以属于不同的任务栈。在这种模式下,谁启动了这个Activity,那么这个Activity就运行在启动它的那Activity在中比如Activity A启动了Activity B (B是标准模式),那么B就会进入到A所在的栈中。当我们用ApplicationContext去启动standard模式的Activity的时候会报错,错误如下:
E/Androl dRunt ime(674) android util. Androi dRuntimeExcept ion:
Callining startActivity from outsIde of an Activity context requires the FLAG_ACTIVITY_NEN_TASK flag. Is this really what you want?
相信这句话读者一定不陌生,这是因为 standard模式的 Activity默认会进入启动它的Activity所属的任务栈中,但是由于非 Activity类型的 Context(如 ApplicationContext)并没有所谓的任务栈,所以这就有问题了。解决这个问题的方法是为待启动 - Activity指定 FLAG ACTIVITY_ NEW TASK标记位,这样启动的时候就会为它创建一个新的任务极这个时候待启动 Activity实际上是以 single Task模式启动的,读者可以仔细体会。
(2) single Top:栈顶复用模式
在这种模式下,如果新 Activity已经位于任务栈的栈顶,那么此 Activity不会被重新创建,同时它的 onNew Intent方法会被回调,通过此方法的参数我们可以取出当前请求的信息。
需要注意的是,这个 Activity的 onCreate、 onStart不会被系统调用,因为它并没有发生改变。如果新 Activity的实例已存在但不是位于栈顶那么新 Activity仍然会重新重建。
举个例子
- 假设目前内的情况为ABCD,其中ABCD为四个 Activity,A位于线底,D位干栈顶
- 这个时候假设要再次启动D,如果D的启动模式为 singleTop,那么栈内的情况仍然为ABCD;如果D的启动模式为 standard
- 那么由于D被重新创建,导致栈内的情况就变为 ABCDD
(3) single Task:栈内复用模式
这是一种实例模式,在这种模式下,只要Activity在一个中存在,那么多次启动此 Activity都不会重新创建实例,和singleTop一样,系统也会回调其onNewIntent.具体一点,当一个具有 single Task模式的 Activity请求启动后比如Activity A,系统首先会寻找是否存在A想要的任务栈,如果不存在,就重新创建个任务栈,然后创建A的实例后把A放到栈中。如果存在A所需的任务栈,这时要看A是否在栈中有实例存在,如果有实例存在,那么系统就会把A调到栈顶并调用它的onNewIntent方法,如果实例不存在,就创建A的实例并把A压入栈中。举几个例子:
- 比如目前任务栈S1中的情况为ABC,这个时候 Activity D以 I single Task模式请求启动,其所需要的任务线为S2,由于S2和D的实例均不存在,所以系统会先创建任务栈S2,然后再创建D的实例并将其入栈到S2.
- 另外一种情况,假设D所需的任务栈为S,其他情况如上面例子1所示,那么由于S1已经存在,所以系统会直接创建D的实例并将其入栈到S1.
- 如果D所需的任务栈为S1,并且当前任务栈S1的情况为ADBC,根据栈内复用的
原则,此时D不会重新创建,系统会把D切换到栈顶并调用其 onNewIntent方法,
同时由于 single Task默认具有 clear Top的效果,会导致栈内所有在D上面的 Activity
全部出栈,于是最终S1中的情况为AD。这一点比较特殊,在后面还会对此种情况
详细地分析。
通过上述3个例子,读者应该能比较清晰地理解 single Task的含义了。
(4)singleInstance:单实例模式
这是一种加强的 single Task模式,它除了具有 single Task
模式的所有特性外,还加强了一点,那就是具有此种模式的 Activity只能单独地位于一个
任务栈中,换句话说,比如 Activity A是 single模式,当A启动后,系统会为它创
建一个新的任务栈,然后A独自在这个新的任各栈中,由于线内复用的特性,后续的请求
均不会创建新的 Activity.,除非这个独特的任务栈被系统销毁了。上面介绍了几种启动模式,这里需要指出一种情况,我们假设目前有2个任务栈,前台任务栈的情况为AB,而后台任务栈的情况为CD,这里假设CD的启动模式均为singleTask.现在请求启动D,那么整个后台任务栈都会被切换到前台,这个时候整个后退列表变成了ABCD。当用户按back键的时候,列表中的 Activity会一一出栈,如图1-7所示。如果不是请求启动D而是启动C,那么情况就不一样了。
IntentFliter的匹配规则
1.action的匹配规则
action是一个字符串,系统预定义了一些action
,同时我们也可以在应用中定义自己的action。action的匹配规则是Intent中
的action必须能够和过滤规则中的action匹配,这里说的匹配是指 action的字符串值完全一样。一个过滤规则中可以有多个 action,那么只要Intent中的 action能够和过滤规则中的任何一个 action相同即可匹配成功。针对上面的过滤规则,只要我们的 Intent中 action值为“com.ryg. charpter_1.c”
或者“com.ryg. charpter_1.d”
都能成功匹配。需要注意的是, Intent中如果没有指定 action,那么匹配失败。
总结一下
action
的匹配要求 Intent中的 action存在且必须和过滤规则中的其中一action
相同,这里需要注意它和category匹规则的不同。另外,actior
区分大小写,大小写不同字符串相同的 action会匹配失败。
2. category
的匹配规则
category是一个字符串,系统预定义了一些 category,同时我们也可以在应用中定义自己的 category. category的匹配规则和 action不同,它要求tent中如果含有 category.,那么所有的 calegory
都必须和过滤规则中的其一个 category相同。换句话说, Intent中如果出现了 category,不管有几个 category,对于每个 category来说,它必须是过滤规则中已经定义了的 category.当然, Intent中可以没有 category,如果没有 category的话,按照上面的描述,这个 Intent仍然可以匹配成功。这里要注意下它和 I action匹配过程的不同, action是要求 Intent中必须有一个 action且必须能够和过滤规则中的某个 acton相同,而 category要求 Intent可以没有 category,但是如果你一旦有 category,不管有几个,每个都要能够和过滤规则中的任何一个 category相同。为了匹配前面的过滤规则中的 category,我们可以写出下面的
Intent, intent addcategory (com ryg category.)ak Intent. addcategory (com. rygategory.d)
亦或者不设置 I category:为什么不设置 category
也可以匹配呢?原因是系统在调用 startActivity或者 start Activity For Result的时候会默认为Intent
加上<“ android. intentcategory. DEFAULT”>
这个 category,所以这个 ategory就可以匹配前面的过滤规则中的第三个 category同时,为了我们的 activity能够接收隐式调用,就必须在 Intent- filter中指定
这个 category,原因刚才已经说明了。
3. data的匹配规则
data的匹配规则和 I action类似,如果过滤规则中定义了data,那么 Intent中必须也要定义可匹配的data.在介绍data的匹配规则之前,我们需要先了解一下data的结构,因为data稍微有些复杂。
data的语法如下所示:
未完待续...