您的位置:首页 > 其它

Activity的生命周期和启动模式(二)

2017-08-15 15:14 218 查看

Activity的启动模式

1.Activity的LaunchMode

在默认情况下,当我们多次启动一个Activity的时候,系统会创建多个实例并把它们放入任务栈中,当我们单击back键,Activity会逐一回退。任务栈是一个“后进先出”的栈结构,每按一个back键就会有一个Activity出栈,直到栈空为止,当栈中无任何Activity的时候,系统就会回收这个任务栈。

四种启动模式:standard、singleTop、singleTask、singleInstance

(1)standard:标准模式,这也是系统默认的模式。每次启动一个Activity都会创建一个新的实例,不管这个实例是否已经存在。在这种模式下,谁启动了这个Activity,那个这个Activity就运行在启动它的那个Activity所在的栈中。当我们用ApplicationContext去启动standard模式的Activity的时候会报错。这是因为standard模式的Activity会默认进入启动它的Activity所属的任务栈中,ApplicationContext并没有任务栈,所以就会报错。这个问题的方法是为待启动Activity指定FLAG_ACTIVITY_NEW_TASK标记位,这样启动的时候就会为它创建一个新的任务栈。

(2)singleTop:栈顶复用模式。如果新Activity已经位于任务栈的栈顶,那么此Activity不会被重新创建,同时它的onNewIntent方法会被调用。如果新Activity的实例已经存在但不是位于栈顶,那么新的Activity仍会被重新创建。

(3)singleTask:栈内复用模式。这种模式下,只要Activity在一个栈中存在,那么多次启动此Activity都不会重新创建实例,和singleTop一样,系统也会调用其onNewIntent。当一个具有singleTask模式的Activity请求启动后,比如Activity A ,系统首先会寻找是否存在A想要的任务栈,如果不存在,就重新创建一个任务栈,然后创建A的实例后把A放到栈中。如果存在A所需的任务栈,这时要看A在栈中是否有实例存在,如果实例存在,那么系统就会把A调到栈顶并调用它的onNewIntent方法,如果不存在,就创建A的实例并把A压入栈中。

(4)singleInstance:单实例模式。具有此模式的Activity只能单独位于一个任务栈中。

TaskAffinity:任务相关性。这个参数标识了一个Activity所需要的任务栈的名字,默认情况下,所有Activity所需的任务栈名字为应用的包名。当然,我们可以为每个Activity都单独指定TaskAffinity属性,这个属性值必须不能和包名相同。

TaskAffinity属性主要和singleTask启动模式或者allowTaskReparenting属性配对使用,在其他情况下没有意义。

当TaskAffinity和singleTask启动模式配对使用的时候,它是具有该模式的Activity的目前任务栈的名字,待启动的Activity会运行在名字和TaskAffinity相同的任务栈中。

有两种方式给Activity指定启动模式:第一种是在清单文件中为Activity指定启动模式;第二种是在代码中给Intent设置标记位来为Activity指定启动模式。

两种方式是有区别的:首先,优先级上,第二种方式的优先级高于第一种,当两种方式同时存在,以第二种方式为准;其次,在限定范围上有所不同,第一种方式无法直接为Activity指定FLAG_ACTIVITY_CLEAR_TOP标识,而第二种方式无法为Activity指定singleInstance模式。

2.Activity的Flags

Activity的Flags有很多,有的标记位可以设定Activity的启动模式,有的标记位可以影响Activity的运行状态

FLAG_ACTIVITY_NEW_TASK:

这个标记位作用是为Activity指定“singleTask”启动模式。

FLAG_ACTIVITY_SINGLE_TOP:

这个标记位作用是为Activity指定“singleTop”启动模式。

FLAG_ACTIVITY_CLEAR_TOP:

具有此标记位的Activity,当它启动时,在同一个任务栈中所有位于它上面的Activity都要出栈。singl

eTask启动模式默认就具有此标记位的效果。

3.IntentFilter的匹配规则

启动Activity分为两种,显示调用和隐式调用。隐式调用需要intent能够匹配目标组件的IntentFilter中所设置过滤信息,如果不匹配将无法启动目标Activity。IntentFilter中的过滤信息有action、category、data

只有Intent同时匹配action类别、category类别、data类别才算完全匹配,只有完全匹配才能成功启动目标Activity

(1)action的匹配规则

存在,匹配任意一个即可

(2)category的匹配规则

可以不设置,要设置的话,每一个都要能够和过滤规则中的任何一个category相同。

(3)data的匹配规则

如果过滤规则中定义了data,那么Intent中必须也要定义可匹配的data

data语法

<data android:scheme="string"
android:host="string"
android:port="string"
android:path="string"
android:pathPattern="string"
android:pathPrefix="string"
android:mimeType="string"/>


data由两部分组成,mimeType和URI。mimeType指媒体类型,而URL中包含数据较多,下面是URL结构:

<scheme>://<host>:<port>/[<path>|<pathPattern>|<pathPrefix>]
 http://www.baidu.com:80/search/info[/code] 
Scheme:URI的模式,比如http、file、content等,如果URI中没有指定scheme,那么整个URI是无效的

Host:URI的主机名,比如www.baidu.com,如果host未指定,那么整个URI是无效的

Port:URI中的端口号,比如说80,仅当URI中指定了scheme和host参数的时候port参数才有意义

path、pathPattern、pathPrefix:这三个参数表示路径信息,其中path表示完整的路径信息;pathPattern也表示完整的路径信息,但是它里面可以包含通配符 *,表示0个或者多个任意字符,需要注意的是,由于正则表达式的规范,如果想表示真实的字符串,那么

“*”要写成“\\*”,"\"要写成"\\\\";pathPrefix表示路径的前缀信息


如下过滤规则:

<intent-filter>

<data android:mimeType="image/*"/>

</intent-filter>


这种规则指定了媒体类型为所有类型的图片,那么Intent中的mimeType属性必须为“image/*”才能匹配,这种情况下虽然过滤规则没有指定URI,但是却有默认值,URI的默认值为content和file。也就是说,虽然没有指定URI,但是Intent中的URI必须为content或者file才能匹配,上面的匹配规则为

intent.setDataAndType(Uri.parse("file://abc"),"image/*");


另外,如果要为Intent指定完整的data,必须要调用setDataAndType方法,不能先调用setData再调用setType,因为这两个方法彼此会清除对方的值
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: