今天,我们来聊聊android的启动模式,在讲android的启动模式之前,我们需要先讲解一下任务栈的概念。
任务桟:
1.程序打开时就创建了一个任务栈, 用于存储当前程序的activity,所有的activity属于一个任务栈。
2.一个任务栈包含了一个activity的集合, 去有序的选择哪一个activity和用户进行交互:只有在任务栈栈顶的activity才可以跟用户进行交互。
3.任务栈可以移动到后台, 并且保留了每一个activity的状态. 并且有序的给用户列出它们的任务, 而且还不丢失它们状态信息。
4.退出应用程序时:当把所有的任务栈中所有的activity清除出栈时,任务栈会被销毁,程序退出。
任务栈的缺点:
1.每开启一次页面都会在任务栈中添加一个Activity,而只有任务栈中的Activity全部清除出栈时,任务栈被销毁,程序才会退出,这样就造成了用,户体验差, 需要点击多次返回才可以把程序退出了。
2.每开启一次页面都会在任务栈中添加一个Activity还会造成数据冗余, 重复数据太多, 会导致内存溢出的问题(OOM)。
为了解决任务栈的缺点,我们引入了启动模式。
启动模式(launchMode)在多个Activity跳转的过程中扮演着重要的角色,它可以决定是否生成新的Activity实例,是否重用已存在的Activity实例,是否和其他Activity实例公用一个task里。这里简单介绍一下task的概念,task是一个具有栈结构的对象,一个task可以管理多个Activity,启动一个应用,也就创建一个与之对应的task。
Activity启动方式有四种,分别是:
[1] standard 模式(默认-标准模式)
这是默认模式,每次激活Activity时都会创建Activity实例,并放入任务栈中。
自己可以启动自己(会创新一个新的Activity)
如:我本身A页面在视图上,这时我在A页面再次启动A页面,会创建一个新的页面覆盖原来的A页面。
[2] singleTop 模式(顶单例模式)
该模式在栈顶只允许有一个相同的Activity,如果在任务的栈顶正好存在该Activity的实例,就重用该实例( 会调用实例的 onNewIntent() ),否则就会创建新的实例并放入栈顶,即使栈中已经存在该Activity的实例,只要不在栈顶,都会创建新的实例。
如:我本身A页面在视图上,这时我在A页面再次启动A页面,不会创建一个新的页面覆盖原来的A页面,而是重用该页面。但如果我在A页面启动B页面,再在B页面启动一次A页面,会会创建一个新的A页面覆盖在B页面上,也就是说这时有三个Activity在桟中。
[3] singleTask 模式(内单例模式)
该模式在桟中只允许有一个相同的Activity,如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的 onNewIntent() )。重用时,会让该实例回到栈顶,因此在它上面的实例将会被移出栈。如果栈中不存在该实例,将会创建新的实例放入栈中。
如:我有三个界面A,B,,C,然后启动A,A在跳转到B,B跳转到C,这时我的桟中有3个Activity,A在最下面,C在最上面,这时我再次启动C,不会新创建一个Activity,而是重用C页面,而如果启动A页面,也不会新创建一个Activity,而是重用之前的A页面,但是要注意,A页面原本是在最下的,这时需要界面显示A页面说明A页面跳到桟的最上面的,那A页面上面的B,C页面会被销毁掉,也就是说并不是将A页面移动到C页面上面,而是把A上面的两个页面干掉,这时A页面自然在最上面了。
[4] singleInstance 模式(全局单例模式)
在一个新栈中创建该Activity的实例,并让多个应用共享该栈中的该Activity实例。一旦该模式的Activity实例已经存在于某个栈中,任何应用再激活该Activity时都会重用该栈中的实例( 会调用实例的 onNewIntent() )。其效果相当于多个应用共享一个应用,不管谁激活该 Activity 都会进入同一个应用中。
如上一模式singleTask 模式的例子,上面C页面跳转到A页面,是销毁上面的Activity,而singleInstance 模式与上一模式的区别是它并不是销毁上面的页面,而是将A页面移动到C页面上。
可以根据实际的需求为Activity设置对应的启动模式,从而可以避免创建大量重复的Activity等问题。
这里说一下如何设置Activity的启动模式,只需要在AndroidManifest.xml里对应的<activity>标签设置Android:launchMode属性,例如:
- <activity
- android:name=".A1"
- android:launchMode="standard" />