Android复习-Acitivity的启动模式

所谓启动模式就是配置文件中的这个属性:

        <activity android:name=".Main3Activity"
            android:launchMode="standard">
        </activity>

launchMode属性用来标识Activity的启动模式,不行的话默认为standard。一共有四种:

在介绍这四种模式之前首先的明确一个任务栈的概念,我们所有的Activity创建的实例都会放入任务栈中统一管理,并且会放入启动它的那个Activity所在的任务栈中,如果不是有Activity启动的,比如在service中启动的,就需要加入为这个Activity创建一个属于自己的栈的启动标记,就这么简单。

可以在同上在清单文件用taskAffinity为Activity指定任务栈,默认为应用包名,并且与singleTask或allowTaskReparenting属性一起使用才有效(后面解释)。


standard :系统默认模式,每次启动一个Activity都会重新创建一个实例入栈,不管这个栈中有没有此Activity的实例。

singleTop :栈顶复用模式,每次启动一个Activity先看看此栈中的栈顶是不是这个Activity的实例,如果是的话,就调用此实例的onNewIntent(Intent intent)方法,把intent传入,不执行其创建的生命流程,例如onCreate,onStart,如果没有的话,就创建一个新的实例压入栈顶。

singleTask:栈内复用模式,每次启动一个Activity先看看有没有此实例需要的栈,如果没有的话就创建栈,并创建此实例入栈,注意啊,这种启动模式有创建栈的功能,像standard和singleTop默认只能进入启动它的activity所在的栈,如果没有的话就会抛异常的。如果已经有栈了的话,就会去看栈内有没有实例,如果没有的话就创建实例入栈,如果已经有的话,就会将此实例上面所有的activity入栈,并且调用他的onNewIntent()方法,然后正常 的执行生命流程,比如正好在栈顶的话,就只会执行onNewIntent方法,如果不是的话,则会执行onRestart,onStart,onResume方法呗。

singleInstance :单例模式,启动这种标记的Activity,不管咋样,都会为它创建一个属于自己的任务栈,然后创建它的实例压入,如果后续再启动这个Activity则不会重新创建实例,达到栈内复用的目的。


这里需要记录一下疑难杂症的问题,

子线程中可以启动Activity吗?

答案:不可以,没反应,再说,启动activity,activity中必然会有操作UI的操作啊,那必然不行啊。


实例分析各种启动方式:

假如A是singleTop模式,在A内有一个按钮,一直启动A自身,那么首先我们进入App启动A(MainActivity3):

03-13 15:09:12.332 23442-23442/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onCreate
03-13 15:09:12.339 23442-23442/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onStart
03-13 15:09:12.340 23442-23442/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onResume

然后点击按钮再次启动A:

03-13 15:09:16.824 23442-23442/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onPause
03-13 15:09:16.825 23442-23442/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onNewIntent
03-13 15:09:16.825 23442-23442/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onResume
再次启动:

03-13 15:09:31.310 23442-23442/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onPause
03-13 15:09:31.311 23442-23442/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onNewIntent
03-13 15:09:31.311 23442-23442/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onResume

我们可以看出,虽然不执行创建的生命流程了,但是还是会执行短暂的onPause,和恢复onResume。


再假如现在A(Main3Activity)是singleTask模式,在A内启动B(Main2Activity),在B内再启动A,首先进入App为A:

03-13 15:15:57.744 28370-28370/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onCreate
03-13 15:15:57.745 28370-28370/ryrj.pzfw.net.activitytest I/mydata: Main3Activity..taskId..1600
03-13 15:15:57.745 28370-28370/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onStart
03-13 15:15:57.745 28370-28370/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onResume
A内启动B:

03-13 15:16:08.150 28370-28370/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onPause
03-13 15:16:08.201 28370-28370/ryrj.pzfw.net.activitytest I/mydata: Main2Activity...onCreate
03-13 15:16:08.202 28370-28370/ryrj.pzfw.net.activitytest I/mydata: Main2Activity..taskId..1600
03-13 15:16:08.202 28370-28370/ryrj.pzfw.net.activitytest I/mydata: Main2Activity...onStart
03-13 15:16:08.202 28370-28370/ryrj.pzfw.net.activitytest I/mydata: Main2Activity...onResume
03-13 15:16:08.682 28370-28370/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onStop

B内启动A:

03-13 15:16:16.996 28370-28370/ryrj.pzfw.net.activitytest I/mydata: Main2Activity...onPause
03-13 15:16:17.007 28370-28370/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onNewIntent
03-13 15:16:17.008 28370-28370/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onRestart
03-13 15:16:17.008 28370-28370/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onStart
03-13 15:16:17.008 28370-28370/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onResume
03-13 15:16:17.438 28370-28370/ryrj.pzfw.net.activitytest I/mydata: Main2Activity...onStop
03-13 15:16:17.438 28370-28370/ryrj.pzfw.net.activitytest I/mydata: Main2Activity...onDestroy

我们可以看到,由于是singleTask模式,所以在B启动A时,因为A已经存在,所以会先执行B的onPause,接着执行A的onNewIntent,onRestart,onStart,onResume,然后因为B在A的上面,所以要让B出栈,所以B再接着执行onStop,onDestroy。


现在假如A是singleInstance模式,在A内启动B,在B内启动A,首先进入App是A:

03-13 15:23:39.086 733-733/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onCreate
03-13 15:23:39.086 733-733/ryrj.pzfw.net.activitytest I/mydata: Main3Activity..taskId..1606
03-13 15:23:39.087 733-733/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onStart
03-13 15:23:39.087 733-733/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onResume

然后启动B:

03-13 15:24:09.015 733-733/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onPause
03-13 15:24:09.073 733-733/ryrj.pzfw.net.activitytest I/mydata: Main2Activity...onCreate
03-13 15:24:09.073 733-733/ryrj.pzfw.net.activitytest I/mydata: Main2Activity..taskId..1607
03-13 15:24:09.073 733-733/ryrj.pzfw.net.activitytest I/mydata: Main2Activity...onStart
03-13 15:24:09.073 733-733/ryrj.pzfw.net.activitytest I/mydata: Main2Activity...onResume
03-13 15:24:09.803 733-733/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onStop

然后B又启动A:

03-13 15:24:22.956 733-733/ryrj.pzfw.net.activitytest I/mydata: Main2Activity...onPause
03-13 15:24:22.970 733-733/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onNewIntent
03-13 15:24:22.970 733-733/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onRestart
03-13 15:24:22.970 733-733/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onStart
03-13 15:24:22.971 733-733/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onResume
03-13 15:24:23.828 733-733/ryrj.pzfw.net.activitytest I/mydata: Main2Activity...onStop

我们可以看出,taskId为他们所在的任务栈,与几种模式相比,在A启动B时,由于是singleInstance模式,B便进入不了这个栈,会为B重新创建一个任务栈的,虽然B此时是standard模式。在B启动A时,这是已有一个A的实例以及它的栈,所以调用A实例的onNewIntent方法,接着执行A,B的正常情景生命流程。


值得注意的是:在非Activity的context中startActivity,必须为这个intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);否则的话,不管Activity在清单文件中声明为何种启动模式,都会抛异常。














猜你喜欢

转载自blog.csdn.net/sinat_31311947/article/details/61916744