Android面试官:这几个问题都回答不出来你真的懂Activity的启动模式吗?

这个模式有些特殊一点,我们先按使用情景介绍它,当我们将要启动该模式的activity时,系统会判断当前是否有它想要的任务栈:

  1. 没有它要的任务栈

系统会新创建一个任务,并将该activity实例化作为该任务的根activity。

  1. 有它要的任务栈

这时候系统会找到该任务栈,如果任务栈里只有它自己则直接调用该activity实例的onNewIntent()方法。如果任务栈中它的上方还存在别的activity,那么这些activity会被全部弹出栈。

至于什么是“它想要的任务栈”,我们会在下面单独分析。

singleInstance:单例模式

基本上跟singleTask相同,会为activity单独创建一个任务并能够复用。但是该模式的activity不允许其他activity跟自己存在于同一个任务中,由此 activity 启动的任何 activity 均会被在其他的任务中打开。

使用Intent标志声明启动模式

此方式可以通过调用intent.addFlags(int flags)或者intent.setFlags(int flags)方法为Intent添加一个标志,用于为将要启动的Activity声明启动模式。

在开始介绍前,先进行几点扫盲科普:

  1. 一个Intent可以设置多个标志,这就是为啥有addflags()setFlags()两个方法的原因了。

  2. 为Intent设置标志的参数都是Intent类的静态常量。

  3. 设置Intent标志不光只有设置activity启动模式这一个功能,设置不同的参数还有其他功能。

  4. 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所属的任务栈,那么这个属性在其他启动模式情况下是什么样的呢?网上好多人都说没有效果,我不信就亲自测试了一下得出以下结论:

  1. 刚介绍 SingleInstance的时候说它跟singleTask一样都会新建一个任务,既然singleTask是根据taskAffinity属性来决定是否需要新建任务的,那么singleInstance是不是也需要指定这个属性呢?

答案是否!只要启动模式为singleInstance它一定会单独开一个任务。

  1. SingleTop模式下指定了taskAffinity属性的值后,他就会神奇的切换到指定的那个任务栈中,除此之外跟原来一样。

  2. 最神奇的就是Standard,它也同样受到了taskAffinity属性的影响,也会切换到指定的那个任务栈中,但当我们多次启动这个activity时它不会再多次的创建实例,而是拉起了之前启动过的实例,更特殊的是,其他三种启动模式在复用之前实例时都会调用onNewIntent()方法,他却不会调用该方法。

taskAffinity的其他作用

taskAffinity还有一个功能就是可以重新定向所属任务,意思就是这个activity原来是属于任务A的,当有一个跟该activity的taskAffin 《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》开源 ity属性值相同的任务B被创建后,这个activity就会从任务A中转移到任务B中。

想要实现这个功能我们还需要allowTaskReparenting属性的配合:

  1. 我们在清单文件中给taskAffinity="A"的activity标签下添加属性android:allowTaskReparenting=true

  2. taskAffinity="B"的任务下启动这个activity,此时这个activity存在于任务B中。

  3. 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

这个启动模式可以分为两种情况:

  1. 未指定taskAffinity

此时该activity可以当应用中的某一模块的入口处

有如下启动流程,微信主页 >> 聊天页 >> 聊天设置页 >> 用户资料页 >> 聊天页,此时我们按下返回键直接回到了微信主页。

  1. 指定了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)]

最后,互联网不存在所谓的寒冬,只是你没有努力罢了!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值