android Activity启动模式LaunchMode

首先说一下为何activity需要启动模式。

记得有一次一位同事问过我一个问题,他从项目首页A跳转选地址页面B,选好地址回到首页面A,一切正常,双击back退出程序,发现还在首页面A。
由于我处理这种问题的时候,一般是B页面直接调用finish方法,结果解决问题绕了很大的弯路,最后发现他是在B页面调用startactivity方法回到A,这也是最根本问题所在。

在默认的情况下,当我们多次启动一个activity的时候,系统就会创建多个实例并把他们一一放入任务栈中,当我们按back键或者调用finish方法的时候,会发现这些activity一一回退。任务栈是一种“后进先出”的栈结构,这比较好理解,每次按一下back键或调用finish方法,就会有一个activity出栈,直到栈空为止,当栈中无任务activity的时候,系统就会回收这个任务栈。
这就有问题了,多次启动同一个activity,系统就会重复创建多个实例,能不能就创建一次呢?这就涉及到了android的启动模式(LaunchMode)

目前activity有四种启动模式:standard(标准模式)、singleTop(栈顶复用模式)、singleTask(栈内复用模式)、singleInstance(单实例模式)。

  1. standard:标准模式,也是系统默认的模式。每次启动一个activity,都会重新创建一个新的实例,不管这个实例是否已经存在。在这种模式下,谁启动了这个activity,这个activity就运行在启动他的哪个activity所在的栈中。
  1. singleTop:栈顶复用模式,在这种模式下,如果新activity已经位于任务栈的栈顶,那么此activity不会被重新创建。也不涉及生命周期的变化,同时他的onNewIntent方法会被调用,通过此方法的参数我们可以取出当前的请求信息。但如果新的activity实例已经存在但并不在栈顶,那么activity仍然会重建。
  1. singleTask:栈内复用模式,这是一种单实例模式,在这种模式下,activity只要在栈中存在(参照属性TaskAffinity),那么多次启动此activity都不会重新创建实例,系统也会回调其onNewIntent。当跳转该activity的时候,默认具有clearTop效果,该activity栈顶所有activity都会销毁。如果不存在,那么根据TaskAffinity查找该任务栈,如果任务栈不存在,先创建任务栈再将activity放入栈中。
  1. singleInstance:单实例模式。这是一种加强的singleTask模式,他和singleTask的区别就是,此模式的activity只能单独的位于一个任务栈。

【说明:此问题我有所怀疑,所以进行测试,如上图三个activity,测试流程activity1 -> activity2 -> activity3 -> activity4 -> back键,发现按完back键之后,回到acvitity1,此测试说明从singleInstance再次启动的activity,放入了默认任务栈】
那么,标准模式的TaskAffinity是否生效呢?继续测试:

【说明:同上面一样的测试,测试流程activity1 -> activity2 -> activity3 -> activity4 -> back键,发现按完back键之后,回到acvitity2,此测试说明从singleInstance再次启动的activity,放在哪个任务栈,是由TaskAffinity决定的】

那么什么是TaskAffinity呢?

TaskAffinity,也就是activity所需的任务栈,翻译为任务相关性。这个参数标识了一个activity所需要的任务栈的名字,默认情况下,所有activity所需的任务栈的名字为应用包名。我们可以为每个activity单独指定TaskAffinity属性,也如上面途中所示。

说到TaskAffinity,不得不提一下allowTaskReparenting属性

allowTaskReparenting一般和TaskAffinity配对使用,当一个应用A启动了应用B的某个Activity后,如果这个activity的allowTaskReparenting属性为true,那么当应用B被启动后,此activity会直接从应用A的任务栈转移到应用B的任务栈中。

提示:参照standard介绍,如不设置该属性,activity应该在A栈中,所以默认情况下如果应用B栈中本就有任务,这时候按back键应该还在B应用中而非A应用中。

上面图片所示的为AndroidMenifest中的启动方法,还有一种Intent中设置标志位来为activity指定启动模式

Intent intent = new Intent(this, GuideDetailsActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

这两种方式都可以为activity指定启动模式,区别1:优先级上,第二种方式的优先级要高于图片中所示,当两种同事存在时,以第二种方式为准。区别2:上述两种方式在限定范围上有所不同,比如第一种方式无法直接为activity设定FLAG_ACTIVITY_CLEAR_TOP标识,而第二种方式无法为activity指定singleInstance

Activity的Flags

activity的Flags有很多,这里列举一些比较常见的标记位。大部分情况下,我们不需要为activity指定标记位,这里只简单介绍下。
FLAG_ACTIVITY_NEW_TASK 这个标记位的作用是指定singleTask启动模式
FLAG_ACTIVITY_SINGLE_TOP 这个标记位的作用是指定singleTop启动模式
FLAG_ACTIVITY_CLEAR_TOP 具有此标记的activity,当他启动时,在同一个任务栈中所有位于他上面的activity都要出栈。这个标记一般和singleTask启动模式一起出现,在这种模式下,如果实例已经存在,那么系统就会调用他的onNewIntent。如果被启动的activity采用standard模式启动,那么他连同他之上的activity都要出栈,系统会创建新的activity实例并放入栈顶。
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 相当于activity的android:excludeFromRecents="true"属性,表示该activity不会出现在历史activity中,对于这个我进行了一个测试:

模拟器测试该属性不生效,本人真机测试用的是乐视手机乐1s,只有按图中,在初始activity中设置才生效,其他activity中无效果。如果有其他情况,欢迎评论中留言,感激不尽!

Activity的IntentFilter匹配规则

启动activity分为两种方法,显式调用和隐式调用,显示调用就是startactivity方式,应该都比较熟悉,隐式调用就是IntentFliter形式,IntentFliter为过滤属性,限制匹配到合适的activity,二者共存的时候,以显式为主。

IntentFliter中的过滤信息有action(行动)、category(类别)、data(数据),下面是一个过滤规则的示例:

只有一个intent同时匹配action类别,category类别,data类别才算完全匹配,只有完全匹配才能成功启动目标activity。

下面详细分析各种属性的匹配规则:

  1. action的匹配规则:action是一个字符串,系统预定义了一些action,同时我们也可以在应用中定义自己的action,action的匹配规则是intent中的action必须能够和过滤规则中的action字符串完全一样,多个action只要能过滤规则中的任何一个action相同即可匹配成功,intent中如果没有指定action,择匹配失败。
  1. category匹配规则:category是一个字符串,系统预定义了一些category,同时我们也可以在应用中定义自己的category,要求intent可以没有category,但是如果你一旦有category,不管有几个,每个都要能够和过滤规则中的任何一个category相同。(如果没设置,默认android.intent.category.DEFAULT)
  1. data的匹配规则:data和action类似,如果规则中定义了data,那么intent中必须也要定义可匹配的data。
    data的语法定义:
    <data android:mimeType="string"
    android:scheme="string"
    android:host="string"
    android:port="string"
    android:path="string"
    android:pathPattern="string"
    android:pathPrefix="string"></data>
    data由两部分组成,mimeType和URI,mimeType指媒体类型,比如:image/jpeg、video/等,可以标识图片、文本、视频等不同的媒体格式(此时如不指定,默认过滤规则为content和file),而URI包含的数据就比较多了,下面是URI的结构:
    <scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]
    比如:
    content://come.exmple.project:200/folder/subfolder/etc
    http://www.baidu.com:80/search/info
    下面介绍每个数据的含义:
    Scheme:URI的模式,比如http、file、content等,如果URI中没有指定scheme,那么整个URI的其他参数无效,这也意味着URI是无效的。
    Host:URI的主机名,比如www.baidu.com,如果host未指定,那么整个URI中的其他参数无效,这也意味着URI是无效的。
    Port:URI的端口号,比如80,仅当URI中指定了scheme和host参数的时候port参数才是有意义的。
    Path、pathPattern和pathPrefix:这三个参数表述路径信息,其中path表示完整的路径信息;pathPattern也标识完整的路径信息,但是他里面可以包含通配符“
    ”,“”标识0个活多个字符,需要注意的是,由于正则表达式的规范,如果想标识真实的字符串,那么“”要写成“\*”,""要写成“\\”;pathPrefix表示路径的前缀信息。
0data匹配规则:要求intent中必须含有data数据,并且data数据能够完全匹配过滤规则中的某一个data,这里的完全匹配是指过滤规则中出现的data部分也出现在了intent中的data。

当我们通过隐式方式启动一个activity的时候,可以做一下判断,看是否有activity能够匹配我们的隐式intent

判断方式有两种

  1. 采用PackageManager的resolveActivity方法或者Intent 的resolveActivity方法,如果他们找不到匹配的activity就会返回null。
  2. PackageManager还提供了queryIntentActivities方法,这个方法和resolveActivity方法不同的是,他不是返回最佳匹配的activity信息而是返回所有成功匹配的activity信息。

相关文章:android Activity生命周期

本文为本人学习笔,如有任何问题,欢迎评论中指出,感激不尽!
二维码.jpg

推荐下本人的微信公众号,本博客及其他方面的消息会定期同步到公众号上面!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,273评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,349评论 3 398
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,709评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,520评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,515评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,158评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,755评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,660评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,203评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,287评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,427评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,122评论 5 349
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,801评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,272评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,393评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,808评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,440评论 2 359