启动模式
Activity储存在Activity栈中,每次创建Activity都会在Activity栈中添加,Activity被销毁时也会从Activity栈中退出。大量的创建、销毁Activity会对系统造成很大开销,为了节省开销,我们可能会复用一些Activity,Activity的启动模式就是为了方便复用Activity而设计的。下面来看一下Activity的4种启动模式:
1. 标准模式 standard
standard是Activity的默认启动模式,如果没有指定启动模式的话,这个Activity就是标准模式。我们可以在AndroidManifast里面为Activity设置启动模式,如下所示:
<activity
android:name=".MainActivity"
android:launchMode="standard" />
启动模式为标准模式的Activity,每次启动的时候都会在Activity栈顶创建一个实例,举个例子:
创建两个Activity,并在各个声明周期中打一个log。当前为MainActivity,点击下面的按钮跳转到启动模式为标准模式的AActivity,这时Activity栈里面有两个Activity,栈顶为AActivity。我们可以通过adb命令来查看当前应用中Activity栈里的信息,在AndroidStudio的Terminal中输入命令:adb shell " dumpsys activity | grep xxx.xxx.xxx.xxx",xxx为你的包名。按下回车后会输出一大段信息,可以从中找到一段这样的:
图中StackId为Activity的Id,sz为栈内Activity的数量,AActivity在栈内的位置位于MainActivity的上方。
上面是MainActivity跳转到AActivity的例子,那么如果多次启动启动模式为标准模式的MainActivity,如下所示:
Activity栈内有两个MainActivity,再来看一下生命周期:
从上图可看到MainActivity被前后创建了两次。既然都是MainActivity,我们可以用其他启动模式来复用MainActivity,减少系统开销。下面来看一下其他启动模式。
2. 栈顶复用模式 singleTop
栈顶复用模式指的是,假如Activity处于栈顶,再次启动这个Activity的时候,复用该Activity。举个例子:
把AActivity的启动模式设置为栈顶复用模式
<activity
android:name=".AActivity"
android:launchMode="singleTop" />
现在从MainActivity跳转到AActivity,再从AActivity创建自己,执行adb命令查看Activity栈,如下所示:
先看一下生命周期。
从MainActivity跳转到AActivity时调用了了onCreate方法,AActivity创建自己时,只调用了onPause方法,然后马上调用onResume方法,说明AActivity在栈顶时,通过栈顶复用模式再次启动自己的时候得到了复用。
再来看一下Activity栈,只有一个AActivity:
启动模式为栈顶复用模式的AActivity在栈顶时,创建自己能得到复用,那么不在栈顶的时候呢?下面来看一下:
新建一个BActivity,现在执行的动作为从MainActivity跳转到AActivity,然后从AActivity跳转到BActivity,然后再从BActivity跳转到AActivity,查看AActivity是否复用。
先看生命周期:
AActivity分别在从MainActivity跳转和从BActivity跳转的时候都调用了onCreate方法,说明创建了两个AActivity。因为从AActivity跳转到BActivity的时候,BActivity在栈顶,所以从BActivity跳转到AActivity,的时候,不能复用。再来看看Activity栈:
一共4个Activity,其中有两个AActivity,没有被复用。这种情况下,如果想复用AActivity,可以使用栈内复用模式。下面来看看栈内复用模式。
3. 栈内复用模式 singleTask
栈内复用模式跟栈顶复用模式相似,只要在同一个栈内启动模式为栈内复用模式的Activity,再次启动的时候就可以复用。先举一个跟栈顶复用模式相似的例子:
把AActivity的启动模式设置为栈顶复用模式
<activity
android:name=".AActivity"
android:launchMode="singleTop" />
现在从MainActivity跳转到AActivity,再从AActivity创建自己,执行adb命令查看Activity栈,如下所示:
从结果来看跟栈顶复用模式一样,AActivity得到了复用。下面再从AActivity跳转到BActivity,然后从BActivity跳转到AActivity,执行adb命令查看Activity栈:
结果也是只有两个Activity,AActivity在栈顶。BActivity去哪了呢?来看一下生命周期:
上图中AActivity只调用了1次onCreate,说明AActivity得到了复用,BActivity在最后执行了onDestroy方法,说明BActivity被销毁了。原来栈内复用模式还有清除顶部的效果,当AActivity跳转到BActivity时,BActivity在栈顶,这个时候BActivity跳转到栈内复用模式的AActivity,AActivity来到了栈顶,之前在AActivity上面的全部被顶出栈外,也就是被清除了。
4.单实例模式 singleInstance
被设置启动模式为单实例模式的Activity独自享有一个Activity栈。举个例子:
把AActivity启动模式设置为单实例模式:
<activity
android:name=".AActivity"
android:launchMode="singleInstance" />
MainActivity跳转到AActivity,然后从AActivity跳转到BActivity,查看生命周期和Activity栈的信息:
上图中,#41和#42是两个不同的Activity,由于AActivity启动模式是单实例模式,独享一个栈,而BActivity不是单实例模式,属于默认栈,这时栈顶为BActivity,点击返回键,退回到MainActivity,如下所示:
再看一下生命周期:
由于栈顶是BActivity,与MainActivity是同一个栈,所以在BActivity出栈被销毁后,MainActivity回到栈顶,而AActivity在另一个栈中,不受影响。这个时候再次跳转到AActivity,AActivity得到复用,生命周期如下所示:
总的来说,单实例模式的Activity就是一旦被创建,除非被销毁,否则无论从哪里跳转该Activity,都能得到复用。
5. Intent中设置启动模式
除了在AndroidManifest里设置Activity的启动模式之外,还能在startActivity时传入的Intent里设置启动模式,下面列举一些常用的启动模式标志:
- FLAG_ACTIVITY_SINGLE_TOP
同栈顶复用模式singleTop - FLAG_ACTIVITY_CLEAR_TOP
类似栈内复用模式singleTask,不同的是,FLAG_ACTIVITY_CLEAR_TOP会把自己和在他上面的Activity全部清除,再重新创建自己,而singleTask不会清除自己。 - FLAG_ACTIVITY_NEW_TASK
类似栈内复用模式singleTask,但不具备清除顶部栈的效果。 - FLAG_ACTIVITY_NEW_DOCUMENT
在一个新的栈中启动Activity
总结
Activity是Android四大组件之一,也是与用户交互最频繁的组件。本篇文章主要介绍了Activity的启动模式。掌握这个知识点能让我们在开发时得到很大的便利,以最正确的姿势写出想要的效果。