-
两种方式中定义的启动模式有些是不一样的,Intent标志中定义的某些启动模式AndroidManifest.xml中没有,反之一样。
-
我们常说的四种启动模式其实说的是AndroidManifest.xml中定义的。
使用AndroidManifest.xml声明启动模式
在清单文件中声明 Activity 时,您可以使用<activity>
元素的 ][launchMode
属性指定 Activity 应该如何与任务关联。
您可以分配给 launchMode
属性的启动模式共有四种:
-
standard
-
singleTop
-
singleTask
-
singleInstance
先不用管他们具体的操作是什么,我们首先要知道这四种启动模式可以分为两大类:
standard
和singleTop
该类启动模式的activity可以被多次的实例化,它们的实例可以放到任何任务中,并且可以位于返回栈的任何位置。
singleTask
和singleInstance
带有此类启动模式的activity,它们只能有一个实例存在,且实例只能存在于单独的任务中。
standard:标准模式
默认启动模式,启动activity时直接创建新的实例并压入启动它的任务栈顶。
singleTop:栈顶复用模式
该模式唯一与standard
不同的就是,如果启动singleTop
模式的activity时发现当前任务的栈顶已经存在着这个activity的实例,那么就不会创建新的实例,而是调用该实例的onNewIntent()
方法。其他的跟标准模式一样。
singleTask:栈内复用模式
这个模式有些特殊一点,我们先按使用情景介绍它,当我们将要启动该模式的activity时,系统会判断当前是否有它想要的任务栈:
- 没有它要的任务栈
系统会新创建一个任务,并将该activity实例化作为该任务的根activity。
- 有它要的任务栈
这时候系统会找到该任务栈,如果任务栈里只有它自己则直接调用该activity实例的onNewIntent()方法。如果任务栈中它的上方还存在别的activity,那么这些activity会被全部弹出栈。
至于什么是“它想要的任务栈”,我们会在下面单独分析。
singleInstance:单例模式
基本上跟singleTask
相同,会为activity单独创建一个任务并能够复用。但是该模式的activity不允许其他activity跟自己存在于同一个任务中,由此 activity 启动的任何 activity 均会被在其他的任务中打开。
使用Intent标志声明启动模式
此方式可以通过调用intent.addFlags(int flags)
或者intent.setFlags(int flags)
方法为Intent添加一个标志,用于为将要启动的Activity声明启动模式。
在开始介绍前,先进行几点扫盲科普:
-
一个Intent可以设置多个标志,这就是为啥有
addflags()
和setFlags()
两个方法的原因了。 -
为Intent设置标志的参数都是Intent类的静态常量。
-
设置Intent标志不光只有设置activity启动模式这一个功能,设置不同的参数还有其他功能。
-
Intent标志中可以对activity启动模式进行操作的标志可多了,我们只介绍特别典型的三种。
Intent.FLAG_ACTIVITY_SINGLE_TOP
同AndroidManifest.xml
方式中的singleTop
启动模式。
Intent.FLAG_ACTIVITY_NEW_TASK
同AndroidManifest.xml
方式中的singleTask
启动模式。
Intent.FLAG_ACTIVITY_CLEAR_TOP
如果即将启动的 activity 已经存在于当前任务栈中,则会弹出销毁它上方的所有 activity,并调用该activity实例的onNewIntent()
方法,而不是启动该 Activity 的新实例。
跟singleTask
有点像但不一样,在AndroidManifest.xml
方式中没有与此对应的值。
singleTask
默认就包含了FLAG_ACTIVITY_CLEAR_TOP
的功能。
关联任务
在分析singleTask
时有提到过该模式下启动activity前会去找“它想要的任务栈”,那么如何去找呢?这就引出了AndroidManifest.xml
中<activity>
标签下的taskAffinity
属性。
taskAffinity 属性
taskAffinity 属性学名任务相关性,说白了其实就是这个参数可以指定当前activity所属任务栈的名字,该属性的值为字符串:
例:android:taskAffinity="com.test.demo.task1"
如果你在<activity>
标签没指定这个属性,那么它就用<application>
标签的taskAffinity
属性,如果<application>
标签下也没指定,它就应用包名当做默认值。
taskAffinity 与 singleTask
了解到taskAffinity
属性后我们在重新梳理一下singleTask
启动模式。
-
如果我们指定了
taskAffinity
属性的值,那么就跟之前分析的一样,创建新任务等等… -
如果我们未指定
taskAffinity
属性的值,新activity就与当前任务的taskAffinity
属性值一样,所以新activity的实例会被放置到当前的任务栈中。
除了singleTask呢?
现在我们知道了taskAffinity
属性可以强行指定activity所属的任务栈,那么这个属性在其他启动模式情况下是什么样的呢?网上好多人都说没有效果,我不信就亲自测试了一下得出以下结论:
- 刚介绍
SingleInstance
的时候说它跟singleTask
一样都会新建一个任务,既然singleTask
是根据taskAffinity
属性来决定是否需要新建任务的,那么singleInstance
是不是也需要指定这个属性呢?
答案是否!只要启动模式为singleInstance
它一定会单独开一个任务。
-
SingleTop
模式下指定了taskAffinity
属性的值后,他就会神奇的切换到指定的那个任务栈中,除此之外跟原来一样。 -
最神奇的就是
Standard
,它也同样受到了taskAffinity
属性的影响,也会切换到指定的那个任务栈中,但当我们多次启动这个activity时它不会再多次的创建实例,而是拉起了之前启动过的实例,更特殊的是,其他三种启动模式在复用之前实例时都会调用onNewIntent()
方法,他却不会调用该方法。
taskAffinity的其他作用
taskAffinity还有一个功能就是可以重新定向所属任务,意思就是这个activity原来是属于任务A的,当有一个跟该activity的taskAffinity属性值相同的任务B被创建后,这个activity就会从任务A中转移到任务B中。
想要实现这个功能我们还需要allowTaskReparenting
属性的配合:
-
我们在清单文件中给
taskAffinity="A"
的activity标签下添加属性android:allowTaskReparenting=true
。 -
在
taskAffinity="B"
的任务下启动这个activity,此时这个activity存在于任务B中。 -
当
taskAffinity="A"
的任务被创建或者被置于前台,该activity将被转移到其任务栈中,位于栈顶位置。
清理任务
如果用户长时间离开任务,则系统会清除所有 Activity 的任务,根 Activity 除外。 当用户再次返回到任务时,仅恢复根 Activity。系统这样做的原因是,经过很长一段时间后,用户可能已经放弃之前执行的操作,返回到任务是要开始执行新的操作。
您可以使用下列几个 Activity 属性修改此行为:
alwaysRetainTaskState
如果在任务的根 Activity 中将此属性设置为 “true”,则不会发生刚才所述的默认行为。即使在很长一段时间后,任务仍将所有 Activity 保留在其堆栈中。
clearTaskOnLaunch
如果在任务的根 Activity 中将此属性设置为 “true”,则每当用户离开任务然后返回时,系统都会将堆栈清除到只剩下根 Activity。 即使只离开任务片刻时间,用户也始终会返回到任务的初始状态。
finishOnTaskLaunch
类似于clearTaskOnLaunch,但是更狠一些,当用户离开任务再回来的时候,整个任务的activity都会清除,连根activity也是,相当于第一次启动这个任务。
启动模式的实际应用
个人觉得常见的四种启动模式中要属singleTop
不是很好理解,其他的还好。
singleTop
singleTop
模式的activity特点就是除了外部可以启动它显示信息外,它也可以用同样的方式启动自己更新显示信息,这样就减少了冗余代码,降低了维护成本。
例:如果让你设计一个带有搜索应用的APP,主页有一个搜索框,输入信息点击搜索按钮进入结果页显示结果,为方便用户使用,结果页也有一个搜索框,跟主页的搜索框功能一样,你会怎么设计?
singleTask
这个启动模式可以分为两种情况:
- 未指定taskAffinity
此时该activity可以当应用中的某一模块的入口处
有如下启动流程,微信主页 >> 聊天页 >> 聊天设置页 >> 用户资料页 >> 聊天页,此时我们按下返回键直接回到了微信主页。
- 指定了taskAffinity
如果利用该启动模式新开了任务,在用户的视角里就相当开了两个应用(在任务管理器中会看到两个最近应用),所以谨慎使用,我能想到的使用情况就是一个Word应用打开了两份文档。
singleInstance
这种情况下不管有多少个任务启动它,它都会作为一个单独任务存在着,这种模式极其特殊,谨慎使用。
例:拨号界面,闹钟界面。
面试复习路线
多余的话就不讲了,接下来将分享面试的一个复习路线,如果你也在准备面试但是不知道怎么高效复习,可以参考一下我的复习路线,有任何问题也欢迎一起互相交流,加油吧!
这里给大家提供一个方向,进行体系化的学习:
1、看视频进行系统学习
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V:vip204888 备注Android获取(资料价值较高,非无偿)
学习交流
群内有许多来自一线的技术大牛,也有在小厂或外包公司奋斗的码农,我们致力打造一个平等,高质量的Android交流圈子,不一定能短期就让每个人的技术突飞猛进,但从长远来说,眼光,格局,长远发展的方向才是最重要的。
35岁中年危机大多是因为被短期的利益牵着走,过早压榨掉了价值,如果能一开始就树立一个正确的长远的职业规划。35岁后的你只会比周围的人更值钱。
04888 备注Android获取(资料价值较高,非无偿)**
[外链图片转存中…(img-SyWcsCw6-1711555543295)]
学习交流
[外链图片转存中…(img-5vvPIfZF-1711555543295)]
[外链图片转存中…(img-plJD9YqN-1711555543295)]
群内有许多来自一线的技术大牛,也有在小厂或外包公司奋斗的码农,我们致力打造一个平等,高质量的Android交流圈子,不一定能短期就让每个人的技术突飞猛进,但从长远来说,眼光,格局,长远发展的方向才是最重要的。
35岁中年危机大多是因为被短期的利益牵着走,过早压榨掉了价值,如果能一开始就树立一个正确的长远的职业规划。35岁后的你只会比周围的人更值钱。