这个模式有些特殊一点,我们先按使用情景介绍它,当我们将要启动该模式的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的taskAffin 《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》开源 ity属性值相同的任务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、看视频进行系统学习
前几年的Crud经历,让我明白自己真的算是菜鸡中的战斗机,也正因为Crud,导致自己技术比较零散,也不够深入不够系统,所以重新进行学习是很有必要的。我差的是系统知识,差的结构框架和思路,所以通过视频来学习,效果更好,也更全面。关于视频学习,个人可以推荐去B站进行学习,B站上有很多学习视频,唯一的缺点就是免费的容易过时。
另外,我自己也珍藏了好几套视频,有需要的我也可以分享给你。
2、进行系统梳理知识,提升储备
客户端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。
系统学习方向:
-
**架构师筑基必备技能:**深入Java泛型+注解深入浅出+并发编程+数据传输与序列化+Java虚拟机原理+反射与类加载+动态代理+高效IO
-
**Android高级UI与FrameWork源码:**高级UI晋升+Framework内核解析+Android组件内核+数据持久化
-
**360°全方面性能调优:**设计思想与代码质量优化+程序性能优化+开发效率优化
Android开源项目《ali1024.coding.net/public/P7/Android/git》 * **解读开源框架设计思想:**热修复设计+插件化框架解读+组件化框架设计+图片加载框架+网络访问框架设计+RXJava响应式编程框架设计+IOC架构设计+Android架构组件Jetpack
-
**NDK模块开发:**NDK基础知识体系+底层图片处理+音视频开发
-
**微信小程序:**小程序介绍+UI开发+API操作+微信对接
-
**Hybrid 开发与Flutter:**Html5项目实战+Flutter进阶
知识梳理完之后,就需要进行查漏补缺,所以针对这些知识点,我手头上也准备了不少的电子书和笔记,这些笔记将各个知识点进行了完美的总结。
3、读源码,看实战笔记,学习大神思路
“编程语言是程序员的表达的方式,而架构是程序员对世界的认知”。所以,程序员要想快速认知并学习架构,读源码是必不可少的。阅读源码,是解决问题 + 理解事物,更重要的:看到源码背后的想法;程序员说:读万行源码,行万种实践。
主要内含微信 MMKV 源码、AsyncTask 源码、Volley 源码、Retrofit源码、OkHttp 源码等等。
最后的最后
对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!
当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的
最后,互联网不存在所谓的寒冬,只是你没有努力罢了!
不可少的。阅读源码,是解决问题 + 理解事物,更重要的:看到源码背后的想法;程序员说:读万行源码,行万种实践。
主要内含微信 MMKV 源码、AsyncTask 源码、Volley 源码、Retrofit源码、OkHttp 源码等等。
最后的最后
对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!
当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的
[外链图片转存中…(img-EVieKTST-1650014898090)]
最后,互联网不存在所谓的寒冬,只是你没有努力罢了!