一直对activity的启动模式和种种Flag意识模模糊糊,抽空详细研究了下,这里做一个记录,防止自己再遗忘。
Activity的加载模式
Android的Activity启动模式有四种
-
standard
标准模式,一般没有设置launchMode的情况下默认是该模式。
05-09 13:56:02.668 21785-21785/com.hj.intentdemo D/>>>>>>>MainActivity: onCreate: 05-09 13:56:02.674 21785-21785/com.hj.intentdemo D/>>>>>>>MainActivity: onResume: 05-09 13:56:05.906 21785-21785/com.hj.intentdemo D/>>>>>>>MainActivity: onPause: 05-09 13:56:05.942 21785-21785/com.hj.intentdemo D/>>>>>>>EActivity: onCreate: 05-09 13:56:05.947 21785-21785/com.hj.intentdemo D/>>>>>>>EActivity: onResume: 05-09 13:56:06.298 21785-21785/com.hj.intentdemo D/>>>>>>>MainActivity: onStop: 05-09 13:56:24.570 21785-21785/com.hj.intentdemo D/>>>>>>>EActivity: onPause: 05-09 13:56:24.598 21785-21785/com.hj.intentdemo D/>>>>>>>EActivity: onCreate: 05-09 13:56:24.601 21785-21785/com.hj.intentdemo D/>>>>>>>EActivity: onResume: 05-09 13:56:24.952 21785-21785/com.hj.intentdemo D/>>>>>>>EActivity: onStop:
在Mainactivity中启动EActivity,在EActivity启动EActivity的生命周期Log。注意跳转到新Activity时,旧Activity的生命周期,先是执行了MainActivity的onPause(),再执行Eactivity的onCreate()、onResume(),之后执行了MainActivity的onStop()。具体原因可以Google或者查看源码,此处不在多说。
-
singleTop
基本和标准模式相同,只有当当前需要跳转的Activity刚好处于栈顶时才不重新创建实例。设置EActivity启动模式为singleTop
05-09 16:00:30.239 16289-16289/com.hj.intentdemo D/>>>>>>>MainActivity: onCreate: 05-09 16:00:30.240 16289-16289/com.hj.intentdemo D/>>>>>>>MainActivity: onResume: 05-09 16:00:50.544 16289-16289/com.hj.intentdemo D/>>>>>>>MainActivity: onPause: 05-09 16:00:50.625 16289-16289/com.hj.intentdemo D/>>>>>>>EActivity: onCreate: 05-09 16:00:50.626 16289-16289/com.hj.intentdemo D/>>>>>>>EActivity: onResume: 05-09 16:00:51.063 16289-16289/com.hj.intentdemo D/>>>>>>>MainActivity: onStop: 05-09 16:00:59.707 16289-16289/com.hj.intentdemo D/>>>>>>>EActivity: onPause: 05-09 16:00:59.707 16289-16289/com.hj.intentdemo D/>>>>>>>EActivity: onResume:
上面是在MainActivity的直接跳转到EActivity中,EActivity跳转到Eactivity执行的生命周期Log
05-09 16:03:45.482 18404-18404/com.hj.intentdemo D/>>>>>>>MainActivity: onCreate: 05-09 16:03:45.483 18404-18404/com.hj.intentdemo D/>>>>>>>MainActivity: onResume: 05-09 16:03:48.467 18404-18404/com.hj.intentdemo D/>>>>>>>MainActivity: onPause: 05-09 16:03:48.503 18404-18404/com.hj.intentdemo D/>>>>>>>EActivity: onCreate: 05-09 16:03:48.504 18404-18404/com.hj.intentdemo D/>>>>>>>EActivity: onResume: 05-09 16:03:48.929 18404-18404/com.hj.intentdemo D/>>>>>>>MainActivity: onStop: 05-09 16:03:53.966 18404-18404/com.hj.intentdemo D/>>>>>>>EActivity: onPause: 05-09 16:03:53.987 18404-18404/com.hj.intentdemo D/>>>>>>>AActivity: onCreate: 05-09 16:03:53.987 18404-18404/com.hj.intentdemo D/>>>>>>>AActivity: onResume: 05-09 16:03:54.457 18404-18404/com.hj.intentdemo D/>>>>>>>EActivity: onStop: 05-09 16:03:57.983 18404-18404/com.hj.intentdemo D/>>>>>>>AActivity: onPause: 05-09 16:03:58.022 18404-18404/com.hj.intentdemo D/>>>>>>>EActivity: onCreate: 05-09 16:03:58.022 18404-18404/com.hj.intentdemo D/>>>>>>>EActivity: onResume: 05-09 16:03:58.426 18404-18404/com.hj.intentdemo D/>>>>>>>AActivity: onStop:
上面执行顺序为MainActivity—>EActivity—>AActivity—>EActivity
-
singleTask
当前activity栈中是否存在activity实例,存在发送intent到activity中,不存在则在新栈中创建新Activity实例
先来看生命周期
05-10 14:58:48.228 4474-4474/com.hj.intentdemo D/>>>>>>>DActivity: onPause: 05-10 14:58:48.267 4474-4474/com.hj.intentdemo D/>>>>>>>EActivity: onCreate: 05-10 14:58:48.267 4474-4474/com.hj.intentdemo D/>>>>>>>EActivity: onResume: 05-10 14:58:48.679 4474-4474/com.hj.intentdemo D/>>>>>>>DActivity: onStop: 05-10 14:58:50.570 4474-4474/com.hj.intentdemo D/>>>>>>>BActivity: onDestroy: 05-10 14:58:50.578 4474-4474/com.hj.intentdemo D/>>>>>>>CActivity: onDestroy: 05-10 14:58:50.584 4474-4474/com.hj.intentdemo D/>>>>>>>DActivity: onDestroy: 05-10 14:58:50.588 4474-4474/com.hj.intentdemo D/>>>>>>>EActivity: onPause: 05-10 14:58:50.593 4474-4474/com.hj.intentdemo D/>>>>>>>AActivity: onResume: 05-10 14:58:50.958 4474-4474/com.hj.intentdemo D/>>>>>>>EActivity: onStop: 05-10 14:58:50.958 4474-4474/com.hj.intentdemo D/>>>>>>>EActivity: onDestroy:
依次由MainActivity—>Activity(singleTAsk)—>BActivity—>CActivity—>DActivity—>EActivity—>AActivity 当由E跳转到A时,销毁了A之前的B、C、D,之后A执行onResume()。和设置intent Falg为
FLAG_ACTIVITY_CLEAR_TOP|FLAG_ACTIVITY_SINGLE_TOP
效果相同。你可能会想不是应该创建新的栈,为什么任务管理器中仍然看到一个,想要实现这种效果你可以加上android:taskAffinity=""
这个属性,上图 -
singleInstance
这个基本和singleTask相同,唯一的区别就是在这个模式下Activity实例所处的task栈中,只能有这么一个Activity实例,不能再有其他实例。一旦该模式的activity的实例已经存在于某个栈中,任何应用在激活该activity时都会重用该栈中的实例。
还是老方法,图片加Log生命周期走起
05-10 15:40:13.526 7364-7364/com.hj.intentdemo D/>>>>>>>MainActivity: onCreate: 05-10 15:40:13.536 7364-7364/com.hj.intentdemo D/>>>>>>>MainActivity: onResume: 05-10 15:40:14.940 7364-7364/com.hj.intentdemo D/>>>>>>>MainActivity: onPause: 05-10 15:40:14.967 7364-7364/com.hj.intentdemo D/>>>>>>>AActivity: onCreate: 05-10 15:40:14.971 7364-7364/com.hj.intentdemo D/>>>>>>>AActivity: onResume: 05-10 15:40:15.390 7364-7364/com.hj.intentdemo D/>>>>>>>MainActivity: onStop: 05-10 15:40:15.830 7364-7364/com.hj.intentdemo D/>>>>>>>AActivity: onPause: 05-10 15:40:15.857 7364-7364/com.hj.intentdemo D/>>>>>>>BActivity: onCreate: 05-10 15:40:15.860 7364-7364/com.hj.intentdemo D/>>>>>>>BActivity: onResume: 05-10 15:40:16.266 7364-7364/com.hj.intentdemo D/>>>>>>>AActivity: onStop: 05-10 15:40:20.461 7364-7364/com.hj.intentdemo D/>>>>>>>BActivity: onPause: 05-10 15:40:20.495 7364-7364/com.hj.intentdemo D/>>>>>>>CActivity: onCreate: 05-10 15:40:20.500 7364-7364/com.hj.intentdemo D/>>>>>>>CActivity: onResume: 05-10 15:40:20.898 7364-7364/com.hj.intentdemo D/>>>>>>>BActivity: onStop: 05-10 15:40:23.069 7364-7364/com.hj.intentdemo D/>>>>>>>CActivity: onPause: 05-10 15:40:23.360 7364-7364/com.hj.intentdemo D/>>>>>>>CActivity: onStop: 05-10 15:40:26.948 7364-7364/com.hj.intentdemo D/>>>>>>>CActivity: onResume: 05-10 15:40:28.769 7364-7364/com.hj.intentdemo D/>>>>>>>CActivity: onPause: 05-10 15:40:29.270 7364-7364/com.hj.intentdemo D/>>>>>>>CActivity: onStop: 05-10 15:40:29.270 7364-7364/com.hj.intentdemo D/>>>>>>>CActivity: onDestroy:
启动顺序为MainActivity—>AActivity(singleTask)—>BActivity(singleTask)—>CActivity。CActivity没有设置taskAffinity属性,默认是和MainActivity处于同一Task中。
多任务管理器直跳转到CActivity,back键返回。直接到主界面了,并没有出现MainActivity。生命周期也没有出现MainActivity被结束的生命周期,重新点击启动app,生命周期中出现了MainActivity的onResume()。
核心特性
- taskAffinity
- launchMode
- allowTaskReparenting
- clearTaskOnLaunch
- alwaysRetainTaskState
- finishOnTaskLaunch
Intent Flag
核心Flag约有三个:
- FLAG_ACTIVITY_NEW_TASK
- FLAG_ACTIVITY_CLEAR_TOP
- FLAG_ACTIVITY_SINGLE_TOP
常用Flag
-
FLAG_ACTIVITY_BROUGHT_TO_FRONT
效果和启动模式的singleTask一样
-
FLAG_ACTIVITY_CLEAR_TOP
Task中包含A、B、C、D。D启动B,Task为A、B。下面是跳转过程中Activity生命周期的log
05-09 17:07:50.622 13590-13590/com.hj.intentdemo D/>>>>>>>MainActivity: onCreate: 05-09 17:07:50.623 13590-13590/com.hj.intentdemo D/>>>>>>>MainActivity: onResume: 05-09 17:07:56.066 13590-13590/com.hj.intentdemo D/>>>>>>>MainActivity: onPause: 05-09 17:07:56.113 13590-13590/com.hj.intentdemo D/>>>>>>>AActivity: onCreate: 05-09 17:07:56.114 13590-13590/com.hj.intentdemo D/>>>>>>>AActivity: onResume: 05-09 17:07:56.560 13590-13590/com.hj.intentdemo D/>>>>>>>MainActivity: onStop: 05-09 17:08:00.333 13590-13590/com.hj.intentdemo D/>>>>>>>AActivity: onPause: 05-09 17:08:00.359 13590-13590/com.hj.intentdemo D/>>>>>>>BActivity: onCreate: 05-09 17:08:00.359 13590-13590/com.hj.intentdemo D/>>>>>>>BActivity: onResume: 05-09 17:08:00.768 13590-13590/com.hj.intentdemo D/>>>>>>>AActivity: onStop: 05-09 17:08:03.945 13590-13590/com.hj.intentdemo D/>>>>>>>BActivity: onPause: 05-09 17:08:03.980 13590-13590/com.hj.intentdemo D/>>>>>>>CActivity: onCreate: 05-09 17:08:03.981 13590-13590/com.hj.intentdemo D/>>>>>>>CActivity: onResume: 05-09 17:08:04.371 13590-13590/com.hj.intentdemo D/>>>>>>>BActivity: onStop: 05-09 17:08:06.294 13590-13590/com.hj.intentdemo D/>>>>>>>CActivity: onPause: 05-09 17:08:06.312 13590-13590/com.hj.intentdemo D/>>>>>>>DActivity: onCreate: 05-09 17:08:06.313 13590-13590/com.hj.intentdemo D/>>>>>>>DActivity: onResume: 05-09 17:08:06.738 13590-13590/com.hj.intentdemo D/>>>>>>>CActivity: onStop: 05-09 17:08:15.773 13590-13590/com.hj.intentdemo D/>>>>>>>CActivity: onDestroy: 05-09 17:08:15.814 13590-13590/com.hj.intentdemo D/>>>>>>>DActivity: onPause: 05-09 17:08:15.824 13590-13590/com.hj.intentdemo D/>>>>>>>BActivity: onDestroy: 05-09 17:08:15.849 13590-13590/com.hj.intentdemo D/>>>>>>>BActivity: onCreate: 05-09 17:08:15.849 13590-13590/com.hj.intentdemo D/>>>>>>>BActivity: onResume: 05-09 17:08:16.248 13590-13590/com.hj.intentdemo D/>>>>>>>DActivity: onStop: 05-09 17:08:16.248 13590-13590/com.hj.intentdemo D/>>>>>>>DActivity: onDestroy:
从生命周期中可以看出,D跳转到B时,会销毁C之后销毁B重新创建,再销毁D。有兴趣的可以直接跳转到A,观察B和C的生命周期情况。
你可能会想到,如何能让B不创建直接跳转呢?可以设置B的launchMode为
singleTop
或者跳转时设置Flag为FLAG_ACTIVITY_CLEAR_TOP
时同时设定为FLAG_ACTIVITY_SINGLE_TOP
intent.setFlags(FLAG_ACTIVITY_CLEAR_TOP|FLAG_ACTIVITY_SINGLE_TOP);
这样就可以不创建B的实例,B的生命周期应该会只执行
onResume()
05-09 17:18:33.516 20964-20964/com.hj.intentdemo D/>>>>>>>CActivity: onPause: 05-09 17:18:33.544 20964-20964/com.hj.intentdemo D/>>>>>>>DActivity: onCreate: 05-09 17:18:33.544 20964-20964/com.hj.intentdemo D/>>>>>>>DActivity: onResume: 05-09 17:18:33.978 20964-20964/com.hj.intentdemo D/>>>>>>>CActivity: onStop: 05-09 17:18:34.446 20964-20964/com.hj.intentdemo D/>>>>>>>CActivity: onDestroy: 05-09 17:18:34.462 20964-20964/com.hj.intentdemo D/>>>>>>>DActivity: onPause: 05-09 17:18:34.478 20964-20964/com.hj.intentdemo D/>>>>>>>BActivity: onResume: 05-09 17:18:34.887 20964-20964/com.hj.intentdemo D/>>>>>>>DActivity: onStop: 05-09 17:18:34.887 20964-20964/com.hj.intentdemo D/>>>>>>>DActivity: onDestroy:
上面部分生命周期(从C跳转D开始)可以看出,D跳转到B时,销毁了C、D,B只执行了
onResume()
和我们猜想的相同。该模式还可以和
FLAG_ACTIVITY_NEW_TASK
结合使用,用于启动一个Task中的根Activity,它会把那个Task中任何运行的实例带入前台,然后清除它直到根Activity。这非常有用,例如,当你要从Notification Manager处启动一个Activity,就需要设置为该Flag。 -
FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
设置该种Flag时,会在Activity栈中加入“还原点”,当直接点击home退出到主界面后再回来时并不会回到栈顶Activity,此时会清除Task中设置为“还原点”的Activity及其之上的所有Activity。
直接上log,下面依次由A—>B—>C(设置为
FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
)—>D—>E的部分生命周期(在E按下home键)05-09 17:53:37.468 32462-32462/com.hj.intentdemo D/>>>>>>>EActivity: onPause: 05-09 17:53:38.039 32462-32462/com.hj.intentdemo D/>>>>>>>EActivity: onStop: 05-09 17:53:49.457 32462-32462/com.hj.intentdemo D/>>>>>>>CActivity: onDestroy: 05-09 17:53:49.521 32462-32462/com.hj.intentdemo D/>>>>>>>DActivity: onDestroy: 05-09 17:53:49.558 32462-32462/com.hj.intentdemo D/>>>>>>>EActivity: onDestroy: 05-09 17:53:49.563 32462-32462/com.hj.intentdemo D/>>>>>>>BActivity: onResume:
E进入后台时执行onPause()、onStop(),再次进入前台时,销毁了“还原点”(C之上包含C)之前的所有Activity。
-
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
设置了该Flag,启动的Activity就不会出现在最近任务列表中。这样说可能很抽象,直接上图
上图代码区分就是设置与否
intent.setFlags(FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
你也可以在Mainfest下Activity标签加上android:excludeFromRecents =“true”
属性就可以达到相同的效果。设置Flag可以让开发者使用已发布的app功能时使其不存在于应用列表下。当然你也可以设置你的launcherActivity为该属性就可以使你的程序不在最近任务列表了。这样你就可以放心开发不可描述的应用了[奸笑] -
FLAG_ACTIVITY_NEW_TASK
在新的Task中启动Activity,需要配合
android:taskAffinity=""
属性一块使用,才能达到单独任务列表 -
FLAG_ACTIVITY_NO_ANIMATION
设置该Flag,Activity切换时不会产生动画效果
-
FLAG_ACTIVITY_NO_HISTORY
Activity不会留在Task栈中,用户一旦离开即销毁Activity。下面是启动MainActivity—>AActivity。切换到后台后重新回来的生命周期
05-11 01:14:44.545 10514-10514/com.hj.intentdemo D/>>>>>>>MainActivity: onCreate: 05-11 01:14:44.547 10514-10514/com.hj.intentdemo D/>>>>>>>MainActivity: onResume: 05-11 01:14:46.039 10514-10514/com.hj.intentdemo D/>>>>>>>MainActivity: onPause: 05-11 01:14:46.053 10514-10514/com.hj.intentdemo D/>>>>>>>AActivity: onCreate: 05-11 01:14:46.054 10514-10514/com.hj.intentdemo D/>>>>>>>AActivity: onResume: 05-11 01:14:46.524 10514-10514/com.hj.intentdemo D/>>>>>>>MainActivity: onStop: 05-11 01:14:48.757 10514-10514/com.hj.intentdemo D/>>>>>>>AActivity: onPause: 05-11 01:14:49.262 10514-10514/com.hj.intentdemo D/>>>>>>>AActivity: onStop: 05-11 01:14:53.225 10514-10514/com.hj.intentdemo D/>>>>>>>MainActivity: onResume: 05-11 01:14:53.226 10514-10514/com.hj.intentdemo D/>>>>>>>AActivity: onDestroy:
可以清晰的看出,当重新回到前台时,MainActivity进入onResume(),AActivity被销毁了
-
FLAG_ACTIVITY_REORDER_TO_FRONT
设置该Flag,会将已经创建的Activity移动到Task的顶端,下面还是先来看下生命周期log
05-11 03:06:52.018 3038-3038/com.hj.intentdemo D/>>>>>>>MainActivity: onCreate: 05-11 03:06:52.034 3038-3038/com.hj.intentdemo D/>>>>>>>MainActivity: onResume: 05-11 03:06:54.443 3038-3038/com.hj.intentdemo D/>>>>>>>MainActivity: onPause: 05-11 03:06:54.469 3038-3038/com.hj.intentdemo D/>>>>>>>AActivity: onCreate: 05-11 03:06:54.471 3038-3038/com.hj.intentdemo D/>>>>>>>AActivity: onResume: 05-11 03:06:55.169 3038-3038/com.hj.intentdemo D/>>>>>>>MainActivity: onStop: 05-11 03:06:55.772 3038-3038/com.hj.intentdemo D/>>>>>>>AActivity: onPause: 05-11 03:06:55.785 3038-3038/com.hj.intentdemo D/>>>>>>>BActivity: onCreate: 05-11 03:06:55.786 3038-3038/com.hj.intentdemo D/>>>>>>>BActivity: onResume: 05-11 03:06:56.391 3038-3038/com.hj.intentdemo D/>>>>>>>AActivity: onStop: 05-11 03:06:56.963 3038-3038/com.hj.intentdemo D/>>>>>>>BActivity: onPause: 05-11 03:06:56.988 3038-3038/com.hj.intentdemo D/>>>>>>>CActivity: onCreate: 05-11 03:06:56.988 3038-3038/com.hj.intentdemo D/>>>>>>>CActivity: onResume: 05-11 03:06:57.641 3038-3038/com.hj.intentdemo D/>>>>>>>BActivity: onStop: 05-11 03:06:58.251 3038-3038/com.hj.intentdemo D/>>>>>>>CActivity: onPause: 05-11 03:06:58.260 3038-3038/com.hj.intentdemo D/>>>>>>>AActivity: onResume: 05-11 03:06:58.956 3038-3038/com.hj.intentdemo D/>>>>>>>CActivity: onStop:
启动顺序为MainActivity—>AActivity—>BActivity—>CActivity—>AActivity。我们可以看出,当重新启动AActivity时,只是重新调整了Task。可以理解为和
FLAG_ACTIVITY_CLEAR_TOP
效果相反。 -
FLAG_ACTIVITY_SINGLE_TOP
设置了该Flag,当启动的Activity处于栈顶则不创建新的Activity实例。
<font size=4 color=#fe0b0b >注意:如果是从BroadcastReceiver启动一个新的Activity,或者是从Service往一个Activity跳转时,不要忘记添加Intent的Flag为FLAG_ACTIVITY_NEW_TASK。</font>