Activity的任务栈Task以及启动模式与Intent的Flag详解(经典博文,值得收藏

与 “singleTask” 基本相同,总是该Activity始终是其所在task中唯一仅有的成员;之后在该activity中启动的activity都不会在其所在的task中.

总结

  1. 当作为startActivityForResult启动的目标时(下文中的它都是指被启动的activity)
  2. 4.x版本.在新的任务栈中启动,并立刻在启动它的activity中的onActivityResult中返回一个为cancel的resultCode.singleInstance的特点还在
  3. 5.x版本.并不会在新的任务栈中启动,而是直接在当前任务栈启动(会出现多个实例),启动它的activity的onActivityResult方法会在它关闭后,正常回调.重点是被它开启的activity将运行在另外一个新的任务栈中.
应用场景
  1. 呼叫来电界面 InCallScreen

常用的Intent Flag

  1. FLAG_ACTIVITY_NEW_TASK

文档摘录: When using this flag, if a task is already running for the activity you are now starting, then a new activity will not be started; instead, the current task will simply be brought to the front of the screen with the state it was last in. See FLAG_ACTIVITY_MULTIPLE_TASK for a flag to disable this behavior.`当使用这个flag时,如果task中已经有了你要启动的activity的话,就不再启动一个新的activity了,当前task会被带到前台(不管这个activity是否在前台,有可能activity上边还压有别的activity).如果不想要这种行为,可以用FLAG_ACTIVITY_MULTIPLE_TASK.

比如说原来栈中情况是A,B,C,在C中启动D,如果在Manifest.xml文件中给D添加了Affinity的值和C所在的Task中的不一样的话,则会在新标记的Affinity所存在的Task中看是否这个activity已经启动,如果没启动,则直接将activity启动.如果启动了,直接将D所在的task带入到前台;如果是默认的或者指定的Affinity和Task一样的话,就和标准模式一样了启动一个新的Activity.

  1. FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET | FLAG_ACTIVITY_NEW_DOCUMENT (API21)

FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET在API 21的时候,被FLAG_ACTIVITY_NEW_DOCUMENT代替

如果一个Intent中包含此属性,则它转向的那个Activity以及在那个Activity其上的所有Activity都会在task重置时被清除出task。当我们将一个后台的task重新回到前台时,系统会在特定情况下为这个动作附带一个FLAG_ACTIVITY_RESET_TASK_IF_NEEDED标记,意味着必要时重置task,这时FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET就会生效。经过测试发现,对于一个处于后台的应用,如果在launcher中点击应用,这个动作中含有FLAG_ACTIVITY_RESET_TASK_IF_NEEDED标记,长按Home键,然后点击最近记录,这个动作不含FLAG_ACTIVITY_RESET_TASK_IF_NEEDED标记,所以前者会清除,后者不会.
应用场景:
比如我们在应用主界面要选择一个图片,然后我们启动了图片浏览界面,但是把这个应用从后台恢复到前台时,为了避免让用户感到困惑,我们希望用户仍然看到主界面,而不是图片浏览界面,这个时候我们就要在转到图片浏览界面时的Intent中加入此标记

5.0之前,Activity1用该flag启动Activity2在OverviewScreen中是没有分开的.也就是说如果back到后台后,再通过launcher中点击app的icon进入,将直接进入Activity1,并且无法回到activity2的界面.
5.0之后,OverviewScreen中,会将两个activity分开.可以返回指定想要的activity.

  1. FLAG_ACTIVITY_MULTIPLE_TASK

不建议使用此标记,除非你自己实现了应用程序的启动器。结合FLAG_ACTIVITY_NEW_TASK这个标记,即使要启动的activity已经存在一个task在运行,也会新启动一个task来运行要启动的activity

系统缺省是不带任务管理器的,所以当你使用这个标签的时候,你必须确保你能从你启动的task中返回回来。
如果没有设置FLAG_ACTIVITY_NEW_TASK,这个标记被忽略

  1. FLAG_ACTIVITY_CLEAR_TASK

文档原文:If set in an Intent passed to Context.startActivity(), this flag will cause any existing task that would be associated with the activity to be cleared before the activity is started. That is, the activity becomes the new root of an otherwise empty task, and any old activities are finished. This can only be used in conjunction with FLAG_ACTIVITY_NEW_TASK.
个人翻译:这个flag会导致,在这个activity启动之前,任何与该activity相关的task都会被清除.也就是说,这个activity将会是一个空task的最底部的activity,之前所有的activity都会被finish掉.这个flag只能和FLAG_ACTIVITY_NEW_TASK结合使用.
比如说原来栈中情况是A,B,C,D,在D中启动B(加入该flag),中间过程是A,B,C依次destory,D先onPause,随后BonCreate,onStart,onResume.D再onStop,onDestory.最后只有一个B在栈底.(无论taskAffinity…?)

  1. FLAG_ACTIVITY_SINGLE_TOP

相当于launchMode中的singleTop,比如说原来栈中情况是A,B,C,D,在D中启动D(加入该flag),栈中的情况还是A,B,C,D.

  1. FLAG_ACTIVITY_CLEAR_TOP

不同于launchMode中的singleTask,比如说原来栈中情况是A,B,C,D,在D中启动B(加入该flag), 栈中的情况将为A,B.但是B会重新onCreate()…,并没有执行onNewIntent().如果希望与singleTask效果相同,可以加入FLAG_ACTIVITY_SINGLE_TOP.

  1. FLAG_ACTIVITY_REORDER_TO_FRONT

这个跟上边FLAG_ACTIVITY_BROUGHT_TO_FRONT的是容易混淆的.比如说原来栈中情况是A,B,C,D,在D中启动B(加入该flag),栈中的情况会是A,C,D,B.(调用onNewIntent())

  1. FLAG_ACTIVITY_BROUGHT_TO_FRONT

这个是最容易让人误解的flag了.跟FLAG_ACTIVITY_REORDER_TO_FRONT是不一样的.不是由我们一般开发者使用的flag.
文档中解释:This flag is not normally set by application code, but set for you by the system as described in the launchMode documentation for the singleTask mode.

  1. FLAG_ACTIVITY_NO_HISTORY

A启动B(加入该Flag),B启动C.在C返回,将直接返回到A.B在A正常onResume后,才会调用onStop,onDestory...
而且被这个flag启动的activity,它的onActivityResult()永远不会被调用

  1. FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

我所理解的,加了这个flag启动的activity所在的task(必须是该task中最底部的activity)将不会在多任务界面出现.一般配合FLAG_ACTIVITY_NEW_TASK使用,这样新的任务栈,在最近使用列表中,就不会出现.

  1. FLAG_ACTIVITY_FORWARD_RESULT

多个Activity的值传递。A通过startActivityForResult启动B,B启动C,但B为过渡页可以finish了,A在期望C把结果返回.这种情况,B可以在启动C的时候加入该flag.

  1. FLAG_ACTIVITY_NO_USER_ACTION

禁止activity调用onUserLeaveHint()。
onUserLeaveHint()作为activity周期的一部分,它在activity因为用户要跳转到别的activity而退到background时使用。比如,在用户按下Home键(用户的操作),它将被调用。比如有电话进来(不属于用户的操作),它就不会被调用。注意:通过调用finish()时该activity销毁时不会调用该函数。

  1. FLAG_ACTIVITY_RETAIN_IN_RECENTS (API21)

与activity设置autoRemoveFromRecents = false属性效果一样.是指当前activity销毁后,是否还在概览屏幕中显示.(5.0之后生效)

  1. FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

一般为系统使用,比如要把一个应用从后台移到前台,有两种方式:从多任务列表中恢复(不包含该flag);从启动器中点击icon恢复(包含该flag);需结合 FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET | FLAG_ACTIVITY_NEW_DOCUMENT (API21)理解

  1. FLAG_ACTIVITY_PREVIOUS_IS_TOP

即 A—> B —>C,若B启动C时用了这个标志位,那在启动时B并不会被当作栈顶的Activity,而是用A做栈顶来启动C。此过程中B充当一个跳转页面。

典型的场景是在应用选择页面,如果在文本中点击一个网址要跳转到浏览器,而系统中又装了不止一个浏览器应用,此时会弹出应用选择页面。在应用选择页面选择某一款浏览器启动时,就会用到这个Flag。然后应用选择页面将自己finish,以保证从浏览器返回时不会在回到选择页面。
经常与FLAG_ACTIVITY_FORWARD_RESULT 一起使用。

  1. FLAG_ACTIVITY_TASK_ON_HOME

该flag启动的activity,点击返回键会回到launcher.需要与FLAG_ACTIVITY_NEW_TASK一起使用,并且FLAG_ACTIVITY_NEW_TASK模式生效(参考该属性)后,该flag才会起作用.

  1. FLAG_EXCLUDE_STOPPED_PACKAGES

设置之后,Intent就不会再匹配那些当前被停止的包里的组件。如果没有设置,默认的匹配行为会包含这些被停止的包。

  1. FLAG_DEBUG_LOG_RESOLUTION

debug模式可以打印log

Activity的task相关属性

参考: 基础总结篇之三:Activity的task相关

  1. allowTaskReparenting

这个属性用来标记一个Activity实例在当前应用退到后台后,是否能从启动它的那个task移动到有共同affinity的task,“true”表示可以移动,“false”表示它必须呆在当前应用的task中,默认值为false。
比如在app1的activityA中打开app2的activity2,按home键,回到后台后,这时在launcher中点击App1,页面显示的是app1的activityA(是在此时将activity2转移到app2的task中).再点击app2,则显示的是activity2,点击back,则会在app2所在的任务栈中回退.

需要注意的是,如果app1退居后台之后,没有再次启动app1,而是直接启动app2,将不会出现以上现象。重新宿主的动作发生在appB再次启动的过程中

  1. alwaysRetainTaskState

这个属性用来标记应用的task是否保持原来的状态,“true”表示总是保持,“false”表示不能够保证,默认为“false”。此属性只对task的根Activity起作用,其他的Activity都会被忽略。

默认情况下,如果一个应用在后台呆的太久例如30分钟,用户从主选单再次选择该应用时,系统就会对该应用的task进行清理,除了根Activity,其他Activity都会被清除出栈,但是如果在根Activity中设置了此属性之后,用户再次启动应用时,仍然可以看到上一次操作的界面。
这个属性对于一些应用非常有用,例如Browser应用程序,有很多状态,比如打开很多的tab,用户不想丢失这些状态,使用这个属性就极为恰当。

  1. clearTaskOnLaunch

这个属性用来标记是否从task清除除根Activity之外的所有的Activity,“true”表示清除,“false”表示不清除,默认为“false”。同样,这个属性也只对根Activity起作用,其他的Activity都会被忽略。 如果设置了这个属性为“true”,每次用户重新启动这个应用时,都只会看到根Activity,task中的其他Activity都会被清除出栈。

  1. finishOnTaskLaunch

与allowReparenting属性相似,不同之处在于allowReparenting属性是重新宿主到有共同affinity的task中,而finishOnTaskLaunch属性是销毁实例。如果这个属性和android:allowReparenting都设定为“true”,则这个属性优先级高。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

写在最后

今天关于面试的分享就到这里,还是那句话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。

最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。

还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

【Android核心高级技术PDF文档,BAT大厂面试真题解析】

【算法合集】

【延伸Android必备知识点】

家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

【Android核心高级技术PDF文档,BAT大厂面试真题解析】

[外链图片转存中…(img-FXVdPsYk-1711724627486)]

【算法合集】

[外链图片转存中…(img-aLhnk4vb-1711724627486)]

【延伸Android必备知识点】

[外链图片转存中…(img-OeGtaWr1-1711724627486)]

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值