我们首先了解下Activity的四种启动模式分别是:
- standard
标准模式:在不指定启动模式的前提下,系统默认使用该模式启动Activity,每次启动一个Activity都会重写创建一个新的实例,不管这个实例存不存在。
- singleTop
栈顶复用模式 :如果在任务的栈顶正好存在该Activity的实例, 就重用该实例,否者就会创建新的实例并放入栈顶(即使栈中已经存在该Activity实例,只要不在栈顶,都会创建实例)。
- singleTask
栈内复用模式:如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的onNewIntent())。重用时,会让该实例回到栈顶,因此在它上面的实例将会被移除栈。如果栈中不存在该实例,将会创建新的实例放入栈中。
- singleInstance
单例模式:在一个新栈中创建该Activity实例,并让多个应用共享改栈中的该Activity实例。一旦改模式的Activity的实例存在于某个栈中,任何应用再激活改Activity时都会重用该栈中的实例,其效果相当于多个应用程序共享一个应用,不管谁激活该Activity都会进入同一个应用中。
其实上面的解释谁都会说,但是实际上我根本不了解,或者说我没有用过这些,我的Activity启动模式一直是默认的。所以,我们在这里会交大家怎么使用它们。
首先,大家在使用它们之前,要考虑个问题,就是它们为啥会出现?我们为啥需要它们?
然后这里跟大家解释下它们出现的原因:
我们启动Activity的时候都是通过startActivity、startActivityForResult
,刚开始第一个Activity
出现也是通过这个的,不过是隐式调用罢了。那么这么我们启动这么Activity
,总要有个东西管理它们吧。是的,有一个工具来管理它们,叫Activity
管理栈即Task来管理它们,这个栈有什么特点呢?
- 先进后出
- 任务栈内的
Activity
清空后才能退出程序
这样,Task就能管理所有的Activity
的创建和它们的生命周期了,但是这样又有新的问题出现了。举例:
我们开始启动FirstActivity,然后从FIrstActivity跳到SecondActivity,再从SecondActivity跳到ThirdActivity,现在我们要返回FirstActivity.这时我们不能直接
startActivity(new Intent(ThirdActivity.this,FirstActivity.class))
,为什么,因为这样会创建一个新的FirstActivity。所有我们只能在ThirdActivity中finish()
,然后在SecondActivity中的onActivityResult()
方法中再finish()
,这样才返回到了FirstActivity。大家发现了,这样很麻烦。假设你不需要返回刚开始FIrstActivity的实例,新创建也没关系。我就喜欢直接startActivity
跳过去。这样的话,新的问题又产生了,如果你要退出程序怎么办?我们退出程序一般是按返回键退出的。你一直按back
返回键的话,它会先跳到FirstActivity,然后再到SecondActivity,再到FirstActivity,这样才能退出,这样是不是很麻烦,而且用户体验也很不好。
所以,这个使用我们寻找一种解决方法,解决上诉的问题。于是,Google提出了Activity
的四种启动模式。我们现在来分析下四种启动模式。
Standard
Activity
的启动模式为standard
的时候,每次startActivity
时都会产生一个新的对象,就和我们A a = new A()
是一样的。
SignleTop
当
Activity
的启动模式为signleTop
的时候,但它处于栈顶的时候,说的清楚点,就是当前页面现实的Activity
为它的时候,startActivity
的时候跳到的是本对象。如果当前对象不是它本身的时候,它和standard
是一样的。那么这样的话它有啥作用呢?还是举个例子:比如你点美团外卖的时候,手机会收到外卖的进度情况,如果你点击了一条通知,然后会进去一个外卖订单进度显示的界面,如下:
这时,外卖订单信息跟新了,你点击更新的信息,就会直接进去改页面,然后订单信息跟新,这时没有跳转新的页面。不知道这时你是否考虑到一个问题?如果没有跳转界面,那么我在哪儿获取Intent
的消息?当然有方法获取,这时会在onNewIntent(Intent intent)
这个方法中获取Intent
,就不能在生命周期中获取getIntent
,切记!
SignleTask
Activity
的启动模式为SignleTask
的时候,不管怎样跳转到本Activity
的时候,那么任务栈Task就会把它顶到栈顶。这么说比较抽象,那么还是举例子说明吧。我们先来看上面例子中我么遇到的问题:我们开始启动FirstActivity,然后从FIrstActivity跳到SecondActivity,再从SecondActivity跳到ThirdActivity,现在我们要返回FirstActivity。上面已经说了,我么不能在ThirdActivity中直接startActivity()
,因为这样会产生新的实例,而且退出的时候很麻烦。那么当我们的FIrstActivity的启动模式为signleTask
的时候,我们就可以直接这样用了。因为任务栈Task不是产生新的FirstActivity
,而是会把FirstActivity和ThirdActivity中间的Activity全部finish
掉,这样FirstActivity就会在栈顶了,跟我们手动finish()
作用一样的。当然,传递消息也不是走生命周期,也是走OnNewIntent(Intent intent)
方法。这里也说下它的作用,一般它为程序的主界面,即MainActivity
,为什么呢?因为这样不管从哪个Activity
返回主界面的时候直接startActivity
就行,而且保证主界面的唯一性。
SignleInstance
这种启动模式,一般很少见或者很少用。为什么呢?因为它是一个单例。我还是来举例说明吧!我们把FirstActivity的启动模式设置为
signleTask
,SecondActivity的启动模式为standard
,ThirdActivity的启动模式为signleInstance
,这样我们启动FirstActivity的时候系统会自动创建一个任务栈Task1,然后将FirstActivity加入Task1中,跳转到SecondActivity的时候也会将SecondActivity加入到Task1中,但是跳转到ThirdActivity的时候系统会创建一个任务栈Task2,然后将ThirdActivity加入到Task2中,而且Task2只会存在一个Activity
。因为Task2只有一个ThirdActivity
,所以ThirdActivity永远处于栈顶,如果不主动finish()
掉的话,第二次跳转到ThirdActivity的时候,也是通过OnNewIntent(Intent intent)
获取传递消息的。但是记住一个问题,不要把signleInstance
模式的Activity
作为中转站,这样的话系统会把Task2做默认的任务栈,推出程序时会先跳到Task2再退出程序。作用的话,还是举例说明吧!比如A、B、C、D四个Activity
,我希望从A→D,B→D,C→D,或者A→B→D等的时候,D永远只有一个,但是又不会像signleTask
把中间的Activity
全部finish()
掉,这样D就不能和A、B、C在同一个Task里,就可以把D的启动模式设置为signleInstance
。