2024年最全当面试官说一下Activity的启动模式吧-[转](1),2024年最新Android岗大厂面试官常问的那些问题

总结

我最近从朋友那里收集到了2020-2021BAT 面试真题解析,内容很多也很系统,包含了很多内容:Android 基础、Java 基础、Android 源码相关分析、常见的一些原理性问题等等,可以很好地帮助大家深刻理解Android相关知识点的原理以及面试相关知识

这份资料把大厂面试中常被问到的技术点整理成了PDF,包知识脉络 + 诸多细节;还有 高级架构技术进阶脑图 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

这里也分享给广大面试同胞们,希望每位程序猿们都能面试成功~

Android 基础知识点

Java 基础知识点

Android 源码相关分析

常见的一些原理性问题

腾讯、字节跳动、阿里、百度等BAT大厂 2019-2020面试真题解析

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

值得一提的是由于返回栈存储结构的特殊性,外部只能访问到栈顶的Activity,也就是最后入栈的那个。所以一个Activity想要能显示在屏幕上那么它必须存在于栈顶位置。

进栈与出栈

当前 Activity 启动另一个 Activity 时,新的 Activity 会被推送到堆栈顶部,成为焦点显示在屏幕上。 前一个 Activity 仍保留在堆栈中,但是处于停止状态。

用户按“返回”按钮时,当前 Activity 会从堆栈顶部弹出(Activity 被销毁),而前一个 Activity 恢复执行。如果用户继续按“返回”,堆栈中的相应 Activity 就会弹出,以显示前一个 Activity,直到用户返回主屏幕为止(或者,返回任务开始时正在运行的任意 Activity)。 当所有 Activity 均从堆栈中移除后,任务即不复存在。栈也就会被回收掉。

特殊的任务

通过前面的了解,我们知道如果要打开新的界面需要把Activity实例放到当前任务对应的返回栈的栈顶。该操作是不管该Activity之前有没有实例化过或者栈中是否已经存在了的。

但是,有些特殊情况下,我们会发现一些“例外”。

例1:当来自多个不同任务中的应用选择使用系统浏览器访问网页的时候,浏览器应用并不会在每个任务的返回栈中都创建Activity,而是将所有网页以选项卡的形式展示在同一个界面中。

本例中浏览器应用的Activity如果已经实例化过了就不会重新创建。

例2:小明在微信中向你分享了一条微博内容,你打开后跳转到了微博APP中的该条微博详情页,当你看完内容后按返回键退出该界面发现并不是回到了微信聊天界面,而是来到了微博主页(或上一次在微博中停留的界面)。

本例中微博详情页的Activity虽然是由微信应用所在的任务启动,但是没有加入到微信应用的任务中,而是加入到了微博的任务栈中。

管理任务

很显然上述两个例子在实际使用中并不少见,对于这种特殊的情况我们需要针对性的管理任务,而众所周知的启动模式仅仅是其中的一种。

定义启动模式定义Activity的启动模式其实就是定义一个Activity的新实例如何(是否)与当前任务做关联。以什么样的方式进入到当前(或其他)任务中。如果你只说Activity的启动模式有四种,其实是不准确的,因为我们可以通过两种方法定义不同的启动模式:

  • 使用AndroidManifest.xml中定义 在AndroidManifest.xml中标签下使用lauchMode属性来指定当前这个activity的启动模式。

  • 使用Intent标志定义 在调用startActivity(Intent intent)前,通过调用intent.addFlags()或者intent.setFlags()方法为Intent添加一个标志,用于为将要启动的Activity声明启动模式。

那两者有什么区别呢?

上述两种方法均可以为activity声明启动模式,只是使用情景不同。

  1. 如果我们希望某个activity在任何情况下都会执行一种特殊的启动模式,我们就可以采用AndroidManifest.xml的方法声明。
    2.如果我们希望某个activity大多数情况下正常启动,而少数情况下执行特殊的启动模式,我们就可以在需要执行特殊启动模式时在Intent中添加标志声明。
  2. 如果一个activity两种方式都声明了的话,使用Intent标志的方式要比AndroidManifest.xml的优先级高。
    4.两种方式中定义的启动模式有些是不一样的,Intent标志中定义的某些启动模式AndroidManifest.xml中没有,反之一样。
  3. 我们常说的四种启动模式其实说的是AndroidManifest.xml中定义的。
使用AndroidManifest.xml声明启动模式

在清单文件中声明 Activity 时,您可以使用元素的 ][launchMode属性指定 Activity 应该如何与任务关联。

您可以分配给 launchMode 属性的启动模式共有四种: - standard - singleTop - singleTask - singleInstance

先不用管他们具体的操作是什么,我们首先要知道这四种启动模式可以分为两大类:

  • standard和singleTop 该类启动模式的activity可以被多次的实例化,它们的实例可以放到任何任务中,并且可以位于返回栈的任何位置。

  • singleTask和singleInstance 带有此类启动模式的activity,它们只能有一个实例存在,且实例只能存在于单独的任务中。

standard:标准模式

默认启动模式,启动activity时直接创建新的实例并压入启动它的任务栈顶。

singleTop:栈顶复用模式

该模式唯一与standard不同的就是,如果启动singleTop模式的activity时发现当前任务的栈顶已经存在着这个activity的实例,那么就不会创建新的实例,而是调用该实例的onNewIntent()方法。其他的跟标准模式一样。

singleTask:栈内复用模式

这个模式有些特殊一点,我们先按使用情景介绍它,当我们将要启动该模式的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中标签下的taskAffinity属性。

taskAffinity 属性

taskAffinity 属性学名任务相关性,说白了其实就是这个参数可以指定当前activity所属任务栈的名字,该属性的值为字符串:

例:android:taskAffinity=“com.test.demo.task1”

如果你在标签没指定这个属性,那么它就用标签的taskAffinity属性,如果标签下也没指定,它就应用包名当做默认值。

taskAffinity 与 singleTask

了解到taskAffinity属性后我们在重新梳理一下singleTask启动模式。

1.如果我们指定了taskAffinity属性的值,那么就跟之前分析的一样,创建新任务等等…

2.如果我们未指定taskAffinity属性的值,新activity就与当前任务的taskAffinity属性值一样,所以新activity的实例会被放置到当前的任务栈中。

除了singleTask呢?

现在我们知道了taskAffinity属性可以强行指定activity所属的任务栈,那么这个属性在其他启动模式情况下是什么样的呢?网上好多人都说没有效果,我不信就亲自测试了一下得出以下结论:

  1. 刚介绍 SingleInstance的时候说它跟singleTask一样都会新建一个任务,既然singleTask是根据taskAffinity属性来决定是否需要新建任务的,那么singleInstance是不是也需要指定这个属性呢? 答案是否!只要启动模式为singleInstance它一定会单独开一个任务。

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

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

taskAffinity的其他作用

taskAffinity还有一个功能就是可以重新定向所属任务,意思就是这个activity原来是属于任务A的,当有一个跟该activity的taskAffinity属性值相同的任务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不是很好理解,其他的还好。

最后

上面这些公司都是时下最受欢迎的互联网大厂,他们的职级、薪资、福利也都讲的差不多了,相信大家都是有梦想和野心的人,心里多少应该都有些想法。

也相信很多人也都在为即将到来的金九银十做准备,也有不少人的目标都是这些公司。

我这边有不少朋友都在这些厂工作,其中也有很多人担任过面试官,上面的资料也差不多都是从朋友那边打探来的。除了上面的信息,我这边还有这些大厂近年来的面试真题及解析,以及一些朋友出于兴趣和热爱一起整理的Android时下热门知识点的学习资料

部分文件:


网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 19
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值