下周一入职,不熟悉的城市,欣喜,忐忑
一、Activity启动模式
任务栈Task,是一种用来放置Activity实例的容器,以栈的形式盛放(先进后出)。任务栈的基本操作:压栈、出栈,其所存放的Activity不支持重排序,只能根据压栈和出栈操作更改Activity的顺序。
Task被移到后台,成为后台任务栈;Task启动被调到前台,成为前台任务栈;手机页面显示的是前台任务栈中的栈顶元素。
1、standard(标准模式)
Activity的默认加载方式,不管该Activity是否已经存在于栈中,都采用new操作,生命周期从onCreate开始。
例如:此时栈1 - ABCD,D通过Intent跳转到A,变为栈1 - ABCDA,点击返回循序为DCBA
2、singleTop(栈顶复用模式)
如果新Activity已经位于任务栈栈顶,那么此Activity不会被重新创建,同时会回调onNewIntent方法;如果新Activity实例已经存在但不在栈顶,那么Activity依然会被重新创建。
例如:栈1 - ABCD,当ActivityD位于栈顶的时候,如果跳转到它本身的Activity(D),此时不会创建一个新的D实例。如果跳转到B,因为B不在栈顶,所以会新建一个B实例压入到栈中,此时栈1 - ABCDB。
应用实例:有的推送点进去都是同一个Activity,用的就是singleTop
3、singleTask(栈内复用模式)
只要Activity在一个任务栈中存在,那么多次启动此Activity都不会重新创建实例,并回调onNewIntent方法。在此模式下,Task栈中只能有一个对应的Activity实例,通常应用在首页。
例如:栈1 - ABCD,D跳转到B,此时栈1 - AB,CD均被栈弹出销毁了
4、singleInstance(单一实例模式)
会将打开的Activity压入一个新的任务栈中,加强的singleTask模式,此种模式的Activity只能单独地位于一个任务栈中,并且此任务栈只有唯一一个实例。
例如:栈1 - ABC,C跳转到D(singleInstance),此时栈1 - ABC,栈2 - D。
- D跳转到D,栈2不会压入新的D。
- D跳转到C,则根据C对应的launchmode在栈1中进行对应的操作,有两种情况。
① C如果为standard,D跳转到C,栈1 - ABCC,点击返回,还在C,栈1 - ABC,不会回到D。
② C如果为singleTask,此时系统已经存在C实例,系统会将请求发送到这个实例上,但是此时系统不会调用onCreate方法,而是调用onNewIntent方法。
二、给启动Activity的Intent添加flag
Intent.addFlags(int flags)
动画展示工具,帮助认识各个flag作用https://github.com/rome753/ActivityTaskView
1. FLAG_ACTIVITY_CLEAR_TASK:
本flag能造成在新活动启动前,与新活动关联的任务被清空。也就是说,新活动成为新任务的根,旧的活动都被结束了。本flag只能与FLAG_ACTIVITY_NEW_TASK联合使用。
(新Activity启动前,清空其所在的Task)
2. FLAG_ACTIVITY_CLEAR_TOP(相当于singleTask)
新Activity已在当前Task中时,在新Activity上面的Activity会被销毁,新Activity不会重新实例化,只会接收new intent。
Activity处于栈顶时:如果启动模式是"multiple" (默认的),并且没添加FLAG_ACTIVITY_SINGLE_TOP,那么活动会被销毁重新创建;如果启动模式是其他的,或者添加了FLAG_ACTIVITY_SINGLE_TOP,那么只会调用活动的onNewIntent()。
跟FLAG_ACTIVITY_NEW_TASK联合使用效果很好:如果用于启动一个任务中的根活动,会把该任务移到前面并清空至root状态。这特别有用,比如用于从notification manager中启动活动。
3. FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
已废弃。API 21后用FLAG_ACTIVITY_NEW_DOCUMENT。
4. FLAG_ACTIVITY_MULTIPLE_TASK
用于创建一个新任务,并启动一个活动放进去。
总是跟FLAG_ACTIVITY_NEW_DOCUMENT或者FLAG_ACTIVITY_NEW_TASK一起使用;
单独用FLAG_ACTIVITY_NEW_DOCUMENT或者FLAG_ACTIVITY_NEW_TASK时,会在已存在的任务中寻找匹配的Intent,找不到才会创建一个新任务;
使用了本flag不会寻找匹配的Intent,会无条件创建一个新任务。
用了FLAG_ACTIVITY_NEW_TASK就不要用本flag,除非你启动的是应用的launcher。跟FLAG_ACTIVITY_NEW_TASK联合使用能防止把已存在的任务移到前面,会为新活动创建一个新任务,无论已存在的任务中有没有新活动。
因为默认安卓系统中没有提供可视化的任务管理,所以你不应该使用本flag,除非给用户提供可以回到其他任务的方法。
单独用本flag而不用FLAG_ACTIVITY_NEW_DOCUMENT或者FLAG_ACTIVITY_NEW_TASK是无效的。
5. FLAG_ACTIVITY_NEW_DOCUMENT
本flag会给启动的活动开一个新的任务记录。使用了本flag或documentLaunchMode属性时,相同活动的多实例会在最近任务列表中产生不同的记录。
使用本flag比使用documentLaunchMode属性更好,因为documentLaunchMode属性会跟活动绑定,而flag只在需要时添加。
注意本flag的默认词义,活动销毁后最近任务列表中的入口不会移除。这跟使用FLAG_ACTIVITY_NEW_TASK不一样,后者活动销毁后入口会马上移除。你可以用FLAG_ACTIVITY_RETAIN_IN_RECENTS改变这个行为。
本flag可以跟FLAG_ACTIVITY_MULTIPLE_TASK联合使用。单独使用时跟manifest活动中定义documentLaunchMode="intoExisting"效果相同,联合使用时跟manifest活动中定义documentLaunchMode="always"效果相同。
6. FLAG_ACTIVITY_NEW_TASK
新活动会成为历史栈中的新任务(一组活动)的开始。
通常用于具有"launcher"行为的活动:让用户完成一系列事情,完全独立于之前的活动。
如果新活动已存在于一个为它运行的任务中,那么不会启动,只会把该任务移到屏幕最前。
如果新活动要返回result给启动自己的活动,就不能用这个flag。
应用示例:在Service中启动Activity;App为系统Launcher时,跳转到微信无法退出时用到。
7. FLAG_ACTIVITY_NO_ANIMATION
本flag会阻止系统展示活动的当前状态到另一个状态之间的转移动画。这并不意味着永远没有动画 -- 如果另一项活动的改变在当前展示的活动启动前发生并且没有使用本flag,那么动画还会展示。当你要进行一系列活动操作,但是用户看到的动画不应该由第一项改变来驱动,而是由下一项。
8. FLAG_ACTIVITY_NO_HISTORY
新活动不会保留在历史栈中,一旦用户切换到其他页面,新活动会马上销毁。
旧活动的onActivityResult()方法永远不会被触发。
9. FLAG_ACTIVITY_REORDER_TO_FRONT
如果新活动已在任务中,用本flag启动会将它移到任务的历史栈的前面。
如果用了FLAG__ACTIVITY__CLEAR__TOP,本flag就无效。_
10. FLAG_ACTIVITY_RETAIN_IN_RECENTS
默认情况下由FLAG_ACTIVITY_NEW_DOCUMENT创建的新纪录,用户关闭时(按返回键或其他方式结束)它在最近任务中的入口会被移除。如果你想保留入口,就用本flag。
接收的活动可以用autoRemoveFromRecents属性或者调用Activity.finishAndRemoveTask()来覆盖本请求。
11. FLAG_ACTIVITY_SINGLE_TOP(相当于singleTop)
新活动已存在历史栈的顶端时就不会重新启动。
12. FLAG_ACTIVITY_FORWARD_RESULT
(当前活动由源活动启动)本intent从当前活动启动新活动时,源活动的接收目标会从当前活动转移为新活动。新活动调用setResult的数据会传送给源活动。
13. FLAG_ACTIVITY_PREVIOUS_IS_TOP
本intent从当前活动启动新活动时,当前活动不会被视为顶端活动,不管是决定传intent给顶端还是启动新活动。新活动被当做顶端活动使用,假设当前活动立即销毁了。
14. FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
新活动不会保存在最近启动的活动列表中。
相当于在AndroidManifest中的属性为android:excludeFromRecents="true"
15. FLAG_ACTIVITY_BROUGHT_TO_FRONT
本flag一般不由应用代码设置,singleTask模式时系统会给你设置。
16. FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
新活动在新任务中启动或者被放到一个已存在任务的顶端时,会被当做任务的前门来启动。这会导致任何相关性的活动在适当状态下需要拥有这个任务(无论移动活动到它里面或者是移走),或者在需要时简单地重置任务到初始状态。
17. FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
本flag一般不由应用代码设置,活动从历史栈中启动(长按home键)时系统会给你设置。
18. FLAG_ACTIVITY_NO_USER_ACTION
本flag会阻止当前最前面活动的onUserLeaveHint回调,在它被新启动的活动造成paused状态时。
通常,一个活动在受到用户操作而从前面移走的时候会调用上面的回调。该回调标志着活动生命周期中的一个点,在该点活动会隐藏它想要显示的”直到用户看到“的东西,比如闪烁的LED灯。
如果一个活动曾经由非用户驱动的事件比如来电或闹钟启动,应该在startActivity中添加本flag,以保证暂停时活动知道用户并没有看到通知。
19. FLAG_ACTIVITY_TASK_ON_HOME
本flag会造成新的启动任务放在当前主页活动任务(如果有的话)的顶端。也就是说,在任务中按返回键总是会回到主页,即使上一个用户看到的活动不是主页。本flag只能与FLAG_ACTIVITY_NEW_TASK联合使用。
20. FLAG_ACTIVITY_LAUNCH_ADJACENT
本flag只在分屏多窗口模式下使用。新活动会显示在旧活动旁边。本flag只能跟FLAG_ACTIVITY_NEW_TASK联合使用。并且如果你想创建一个已存在活动的新实例,那么要设置FLAG_ACTIVITY_MULTIPLE_TASK。