1.Activity的LaunchMode
为什么会有启动模式一说,当我们创建Activity时,系统会将它们一一放入任务栈中,任务栈是一种“后进先出”的栈结构,也就是最后放入的Activity会在最上面,如果多次启动同一个Activity,系统会反复创建多个实例,这样很多余,所以就有了启动模式这个概念。
1.standard: 标准模式,系统默认的模式,每次启动一个Activity都会重新创建一个实例,不管这个实例是否已经存在。被创建的实例的生命周期,符合典型情况下的生命周期。
standard启动模式下启动的Activity,如果使用ApplicationContext的上下文会报错,这是因为standard模式的Activity默认会进入启动它的Activity所属的任务栈中,但是由于非Activity类型的Context(如ApplicationContext)并没有所谓的任务栈。解决这个问题的方法是为待启动的Activity指定FLAG_ACTIVITY_NEW_TASK标记位,这样启动的时候就会为它创建一个新的任务栈,这个时候启动的Activity实际上是以singleTask模式启动的。
- singleTop: 栈顶复用模式 。 如果要创建的Activity位于栈顶,那么此Activity不会被重新创建,同时它的onNewIntent()会被调用,这个时候它的onCreate(),onStart(),不会被系统调用,因为没有发生改变。如果要创建的Activity不位于栈顶,仍会被重新创建。
3.singleTask: 栈内复用模式。单实例模式,只要要创建的Activity在栈内存在,那么多次启动此Activity都不会重新创建实例,和singleTop一样,系统也会回调其onNewIntent() 。但是singTask默认具有clearTop效果,所以如果要创建的Activity位于栈内,重新创建时,不在栈顶的话,会导致其上的Activity全部出栈。
- singleInstance : 单实例模式。 这是一种加强的singleTask模式,它除了具有singleTask的所有特性之外,还加强了一点,那就是具有此种模式的Activity只能单独的位于一个任务栈中。Activity单独的在这个任务栈中,由于栈内复用的特性,后续的请求均不会创建新的Activity。
2. 给Activity指定启动模式。
1. 通过AndroidManifest.xml来指定。
<activity
......
android:launchMode = "singleTask"
.......
/>
2. 在Intent中设置标志位来为Activity指定启动模式。
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Activity的Flags
-
FLAG_ACTIVITY_NEW_TASK 这个标记位的作用是为Activity指定“singleTask” 启动模式,其效果和在xml中指定该启动模式相同。
-
FLAG_ACTIVITY_SINGLE_TOP 这个标记位的作用是为Activity指定“singTop”启动模式,其效果和在XML中指定该启动模式相同。
3.FLAG_ACTIVITY_CLEAR_TOP 具有此标记位的Activity启动时,在同一个任务栈中所有位于它上面的Activity都要出栈,这个标记位一般会和singleTask启动模式一起出现,在这种情况下,被启动的Activity的实例如果已经存在,那么系统会调用它的onNewIntent()。如果被启动的Activity采用standard模式启动,那么它连同它之上的Activity都要出栈,系统会创建新的Activity实例并放入栈中。 而SingTask默认就具有此标记位的效果。
4.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 具有这个标记位的Activity不会出现在历史Activity列表中,当某些情况下我们不希望用户通过历史列表回到我们的Activity时这个标记比较有用。等同于在XML中设置Activity的属性android:excludeFromRecents = "true"。
Activity的两种启动模式的优先级还是有差别的,第二种方式要高于第一种,当两种同时存在时,以第二种方式为准。但是这两种方式还是有差别的。第一种无法指定FLAG_ACTIVITY_CLEAR_TOP标识,第二种无法为Activity指定singleInstance模式。
3. IntentFliter的匹配规则。
启动Activity分为显式调用和隐式调用。显式调用需要明确的指定被启动对象的组件信息,包括类名和包名。也就是intent.setClass(MainActivity.this,SecondActivity.class);
隐式调用:需要Intent能够匹配目标组件的IntentFilter中所设置的过滤信息,如果不匹配将无法启动目标Activity。IntentFilter中的过滤信息有action、category、data。
1.action
action是一个字符串,action的匹配规则是Intent中的action必须能够和过滤规则中的action匹配,这里说的匹配是指action的字符串值完全一样。一个过滤规则中可以有多个action,那么只要Intent中的action能够和过滤规则中的任何一个action相同即可匹配成功。注意:action是需要区分大小写的。
2.category
category是一个字符串,category匹配规则,Intent中如果已经出现了category,不管有几个category,对于每个category来说,它必须是过滤规则中已定义了的category。当然,Intent中可以没有category,系统会给intent默认加上android.intent.category.DEFAULT这个category。
3.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指媒体类型,如image/jpeg、audio/mpeg4-generic和video/*等。Uri中包括的数据较多,结构如下:
<scheme>: //<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]
Scheme:URI的模式,比如http、file、content等,如果URI中没有指定scheme,那么URI是无效的。
Host:URI主机名,比如www.baidu.com,如果host未指定,那么URI是无效的。
Port:URI的端口号,比如80,仅当URI中指定了scheme和host参数的时候port参数才是有意义的。
path、pathPrefix、pathPattern表示的是路径信息。
欢迎关注个人公众号,加入进来一起学习吧!
平头哥写代码
网友评论