在使用编写界面时,我们可能从来没有关注过Activity的启动模式,其实默认的启动模式为标准的启动模式(standard);在Activity任务栈中,标准的启动模式会为每一个Activity创建一个实例,其实在很多需求中,这样的使用明显是不准确的,我们应该尽可能的将每个Activity的启动模式设置正确以便程序更加健壮。
四大启动模式如下:
standard
singleTop
singleTask
singleInstance
下面我们看看官方对启动模式的解释:
启动模式 | 用例 | 多个实例? | 解释 |
---|---|---|---|
standard | 大多数 Activity 的正常启动 | 是 | 默认值。系统始终会在目标任务中创建新的 Activity 实例并向其传送 Intent。 |
singleTop | 大多数 Activity 的正常启动 | 有条件 | 如果目标任务的顶部已存在一个 Activity 实例,则系统会通过调用该实例的 onNewIntent()方法向其传送 Intent,而不是创建新的 Activity 实例。 |
singleTask | 专用启动(不建议用作常规用途) | 否 | 系统在新任务的根位置创建 Activity 并向其传送 Intent。 不过,如果已存在一个 Activity 实例,则系统会通过调用该实例的 onNewIntent()方法向其传送 Intent,而不是创建新的 Activity 实例。 |
singleInstance | 专用启动(不建议用作常规用途) | 否 | 与“singleTask"”相同,只是系统不会将任何其他 Activity 启动到包含实例的任务中。 该 Activity 始终是其任务唯一仅有的成员。 |
看到上面的的解释是否都明白呢?下面我们使用一个例子来说明一下使用方法, 创建了四个Activity,分别使用Standard、SingleTop、SingleTask、SingleInstance 启动模式, 并且SingleTask作为程序的启动Activity:
每个Activity都是同样的代码,获取到当前Task任务栈中的Activity数量以及跳转到每个Activity的点击事件:
class SingleTaskActivity : AppCompatActivity() {
val TAG = "ActivityManagerDemo"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_single_task)
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
fun getActivityStack(view: View) {
var activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
var appTasks = activityManager.appTasks
for (appTask in appTasks) {
val taskInfo = appTask.taskInfo
Log.d(TAG, taskInfo.numActivities.toString())
}
}
fun standard(view: View) {
// 跳转到标准
startActivity(Intent(this@SingleTaskActivity, StandardActivity::class.java))
}
fun singleInstance(view: View) {
// 单例
startActivity(Intent(this@SingleTaskActivity, SingleInstanceActivity::class.java))
}
fun singleTop(view: View) {
// 栈顶
startActivity(Intent(this@SingleTaskActivity, SingleTopActivity::class.java))
}
fun singleTask(view: View) {
// 去除栈上
startActivity(Intent(this@SingleTaskActivity, SingleTaskActivity::class.java))
}
}
为了方便我们查看,将Standard页面设置为 1 , SingleTop 设置为 2 ,SingleTask 设置为 3, SingleInstance设置为 4;接下来测试Standard启动模式,程序开始进入到SingleTaskActivity。
Standard 模式测试
按照 3 -> 1 -> 1-> 1->1 测试
09-29 09:15:27.036 9208-9208/com.ellison.manager D/ActivityManagerDemo: 当前任务栈中Activity数量为:1 栈id为:26
09-29 09:15:31.752 9208-9208/com.ellison.manager D/ActivityManagerDemo: 当前任务栈中Activity数量为:2 栈id为:26
09-29 09:15:33.486 9208-9208/com.ellison.manager D/ActivityManagerDemo: 当前任务栈中Activity数量为:3 栈id为:26
09-29 09:15:35.267 9208-9208/com.ellison.manager D/ActivityManagerDemo: 当前任务栈中Activity数量为:4 栈id为:26
09-29 09:15:37.236 9208-9208/com.ellison.manager D/ActivityManagerDemo: 当前任务栈中Activity数量为:5 栈id为:26
可以看到,每次跳转都会生成一个StandardActivity实例!
SingleTop模式测试
按照 3 -> 1 -> 2-> 2 测试
09-29 09:16:10.076 9208-9208/com.ellison.manager D/ActivityManagerDemo: 当前任务栈中Activity数量为:1 栈id为:26
09-29 09:16:42.851 9208-9208/com.ellison.manager D/ActivityManagerDemo: 当前任务栈中Activity数量为:2 栈id为:26
09-29 09:16:46.896 9208-9208/com.ellison.manager D/ActivityManagerDemo: 当前任务栈中Activity数量为:3 栈id为:26
09-29 09:16:49.631 9208-9208/com.ellison.manager D/ActivityManagerDemo: 当前任务栈中Activity数量为:3 栈id为:26
在测试的时候,跳转到2之后,2已经处于栈顶,再次点击跳转到SingleTop界面无变化,说明已经复用了栈顶存在Activity。
SingleTask模式测试
按照 3 -> 1 -> 2-> 3 测试
09-29 09:18:27.561 9208-9208/com.ellison.manager D/ActivityManagerDemo: 当前任务栈中Activity数量为:1 栈id为:26
09-29 09:18:33.782 9208-9208/com.ellison.manager D/ActivityManagerDemo: 当前任务栈中Activity数量为:2 栈id为:26
09-29 09:18:40.754 9208-9208/com.ellison.manager D/ActivityManagerDemo: 当前任务栈中Activity数量为:3 栈id为:26
09-29 09:18:43.580 9208-9208/com.ellison.manager D/ActivityManagerDemo: 当前任务栈中Activity数量为:1 栈id为:26
当两个页面跳转完之后再次跳转到SingleTask页面,获取到栈内的数量为1,说明了跳转到SingleTask页面的时候,会将位于SingleTask栈上的所有页面销毁。
SingleInstance模式测试
按照 3 -> 1 -> 2-> 4->1->1->4 测试
09-29 09:18:58.824 9208-9208/com.ellison.manager D/ActivityManagerDemo: 当前任务栈中Activity数量为:1 栈id为:26
09-29 09:19:06.654 9208-9208/com.ellison.manager D/ActivityManagerDemo: 当前任务栈中Activity数量为:2 栈id为:26
09-29 09:19:13.225 9208-9208/com.ellison.manager D/ActivityManagerDemo: 当前任务栈中Activity数量为:3 栈id为:26
09-29 09:19:17.038 9208-9208/com.ellison.manager D/ActivityManagerDemo: 当前任务栈中Activity数量为:1 栈id为:27
09-29 09:19:24.149 9208-9208/com.ellison.manager D/ActivityManagerDemo: 当前任务栈中Activity数量为:4 栈id为:26
09-29 09:19:28.156 9208-9208/com.ellison.manager D/ActivityManagerDemo: 当前任务栈中Activity数量为:5 栈id为:26
09-29 09:19:33.445 9208-9208/com.ellison.manager D/ActivityManagerDemo: 当前任务栈中Activity数量为:1 栈id为:27
SingleInstance模式可能比较难理解,上面没有说到栈id,这是app给每个task设置的栈id,一般一个应用存在同一个栈中,所以id相同,而SingleInstance模式在系统在只存在一个实例,而且还会给Activity分配一个不同的任务栈,所以当我们第一次跳转到SingleInstance的Activity时,会为Activity创建一个新的栈id,等同于该Activity和其他Activity分隔开了,而后面我们再次回到Standard模式的Activity时,又回到了之前的任务栈。
总结
面试首先说出Activity启动模式,再结合实用场景,比如SIngleTask模式:现在许多的应用都是使用Tab页面加载Fragment,此时MainTabActivity就可以使用SingleTask模式,因为当使用多级页面跳转之后再回到MainTabActivity,此时在回退,会发现有多个MainTabActivity,这样设计肯定是不合理的,使用SingleTask模式则很好的解决了这一问题。