为什么会有四种启动方式
Activity之所以会有四种启动方式是因为在Android系统中是通过栈结构来保存我们整个App中的Activity,所以一个符合业务需求的任务调度栈可以提高整个项目的性能,栈结构是后进先出的线性表
如上图所示,在默认情况下,当我们从Activity1启动Activity2时Activity2就会放置在启动它的Activity1上面,这时Activity1虽然没有跟用户进行交互,但是依然在栈中,当用户调用了finish()方法时,Android系统会移除Activity2,Activity1又重新获取焦点跟用户进行交互,这样看似很合理,但是碰上一些特定需求这样的启动方式就显得不是那么和谐了,比如微信的聊天界面,当接收到新消息要弹出Activity,收到十条信息如果用上面的启动方式,那就要启动十个Activity了,这样虽然也可以但是会造成不必要的性能浪费,为了应付不同的需求,Google给Activity设置了四种启动模式。
要使用不同的启动模式,有两种方法,一个是在清单文件注册Activity时加上launchMode这个属性
<span style="font-size:14px;"><activity android:name=".Activity80"
android:launchMode="standard"
/></span>
另个是通过设置Intent的FLag来设置,例如Intent.FLAG_ACTIVITY_CLEAR_TOP这样去启动一个Activity,与在清单文件中指定android:launchMode="singleTop"效果一样,这里就不在累赘了。
下面分析四种启动模式
standard
standard英文就是标准的意思,当我们没有在清单文件中设置启动模式的时候Android系统默认的启动模式就是这个,当以这种模式启动Activity时,系统每次都会创建一个新的Activity实例,然后这个Activity覆盖在原Activity上,图例分析如下:
上面是一个任务栈,当我从A(Activity)启动B时,B就会覆盖到A上面,B启动C,所以C覆盖到B上,当C又重新启动A,这时A又覆盖到C上,依次在栈里创建实例。
singleTop
如果你把Activity设置成这种启动模式,那么当启动这个Activity时系统会判断栈顶的Activity是不是将要启动的Activity(就是自己启动自己),如果是则调用onNewIntent()重新引用这个Activity而不是再重新创建一个Activity置于原Activity顶部,如果不是就创新的Activity置于这个Activity上面,图例分析如下:
A启动B,B启动C,C又启动C,这时就不会创建新的实例置于C上,而是重新引用C,这种启动模式适用于那些界面一样但是数据会变化的,比如手机股票的更新图,股票界面是一样的,但是里面的走势会动态的更新数据。
singleTask
这个启动模式同singleTop有些类似,只是singleTop是检测栈顶元素是否是需要启动的Activity,而singleTask是检测整个栈中是否存在当前要启动的Activity,如果存在就将这个Activity置于栈顶,然后将这个Activity以上的Activity全部销毁,但是这是指在一个App中启动这个singleTask的Activity的情况,如果是别的应用来启动这个Activity,则会新起一个栈。还有一点是如果这个启动模式为singleTask的Activity已经在后台的一个任务栈中,当这个Activity被启动时,它所在的整个栈都会被启动。
singleTask这种启动模式通常被用来退出整个应用,将MainActivity设为singleTask模式,然后退出的Activity转到MainActivity,然后将MainActivity之上的Activity全部清除掉,重写MainActivity的onNewIntent()方法,在方法中finish(),将这最后一个Activity销毁,从而退出整个应用,图例分析如下:
A的启动模式是singleTask,BC是默认启动模式,当A启动B,B启动C,就会依次往上创建实例,但是当C启动A时,不会再重新创建A的实例,而是直接引用A,然后把BC两个Activity从栈中销毁。
singleInstance
如果一个Activity启动模式为singlelnstance,当启动这个Activity时,会新建一个栈,然后这个栈里面只有这一个Activity,这跟浏览器的工作原理有些类似,多个程序访问浏览器时,如果浏览器没有打开,就打开浏览器,如果打开了,就直接在当前浏览器访问,但是始终只打开了一个浏览器。换到Activity上来说就是比如应用A中有一个启动模式设置为singlelnstance的Activity1,如果应用B要启动Activity1,这时如果Activity1已经在任务栈中存在,就不需要重新创建,如果不存在就重新创建,图例如下:
无论什么启动A,A都独立在一个栈里面,这种模式理解起来相对简单,就是类似单例模式,一个任务栈里面只能有它自己一个实例,这种启动模式常用在需要跟程序分离的界面。例如在手机设置向导时调用紧急呼叫,就是采用这种启动模式。
需要注意的一个是如果在一个启动模式为singleTop或singlelnstance的Activity中通过startActivityForResult()方法启动另个Activity时,系统会直接返回Activity.RESULT_CANCELED而不会等待返回,这是因为Android开发人员认为,不同栈之间默认是不能传递数据的,如果要传递只能通过Intent去绑定数据。
总结
合理的设置Activity启动模式会让我们的App运行得更有效率,用户体验更好,但前提是合理使用,如果过度使用Activity任务栈,会导致整个项目的栈管理混乱,产生一些难以解决的bug,所以使用Activity任务栈的时候一定是根据实际需要来设定,而不能为了使用任务栈来使用任务栈。