先对Activity、Intent、返回栈、Activity的状态以及生命周期了解一下。

Activity启动模式分为四种:standard、singleTop、singleTask、singleInstance,可以在 AndroidManifest.xml中的 activity标签中设置,下面一一讲解。

详谈Activity的启动模式_activity启动

standard(标准启动模式)

标准模式是默认的启动模式,可以不用在清单文件中指定,它的特点就是每次启动都会创建一个新的Activity实例,那么启动三次就要点三次Back键才能退回到主界面。这个模式很简单,不再赘述~

详谈Activity的启动模式_日志打印_02

singleTop(栈顶复用模式)

设置此模式的Activity只要位于栈顶,启动它的时候就不会重新创建该Activity,当我们从MainActivity启动FirstActivity,再在FirstActivity启动FirstActivity自己,日志打印如下:

2019-10-12 13:49:21.875 24673-24673/com.example.test E/MainActivity: onPause: 

2019-10-12 13:49:21.926 24673-24673/com.example.test E/FirstActivity: onCreate: --- FirstActivity

2019-10-12 13:49:21.929 24673-24673/com.example.test E/FirstActivity: onStart: 

2019-10-12 13:49:21.931 24673-24673/com.example.test E/FirstActivity: onResume: 

2019-10-12 13:49:22.229 24673-24673/com.example.test E/MainActivity: onStop: 

2019-10-12 13:49:26.437 24673-24673/com.example.test E/FirstActivity: onPause: 

2019-10-12 13:49:26.437 24673-24673/com.example.test E/FirstActivity: onResume: 

2019-10-12 13:49:28.102 24673-24673/com.example.test E/FirstActivity: onPause: 

2019-10-12 13:49:28.103 24673-24673/com.example.test E/FirstActivity: onResume: 

2019-10-12 13:49:28.842 24673-24673/com.example.test E/FirstActivity: onPause: 

2019-10-12 13:49:28.843 24673-24673/com.example.test E/FirstActivity: onResume: 

可以看出来,FirstActivity只是先被暂停,然后重新展示,并没有重新创建。

适用场景:此启动模式适用于启动渠道较多的场景,比如多个应用都会启动这个Activity,或者推送场景,收到多条推送消息,总不能点一条推送消息就重新创建一个Activity实例吧~

singleTask(栈内复用模式)

与singleTop模式类似,只不过该模式是相对于任务栈(Task)来说,只要在同一个Task中存在此Activity,则启动此Activity不会重新创建新的实例。首先我把MainActivity的启动模式设置为singleTask,当我依次依次启动MainActivity >> FirstActivity >> SecondActivity >> ThirdActivity,日志打印如下:

由MainActivity启动FirstActivity:

2019-10-12 14:14:11.092 31496-31496/com.example.test E/MainActivity: onCreate: --- MainActivity

2019-10-12 14:14:11.096 31496-31496/com.example.test E/MainActivity: onStart: 

2019-10-12 14:14:11.098 31496-31496/com.example.test E/MainActivity: onResume: 

2019-10-12 14:14:13.585 31496-31496/com.example.test E/MainActivity: onPause: 

2019-10-12 14:14:13.624 31496-31496/com.example.test E/FirstActivity: onCreate: --- FirstActivity

2019-10-12 14:14:13.626 31496-31496/com.example.test E/FirstActivity: onStart: 

2019-10-12 14:14:13.627 31496-31496/com.example.test E/FirstActivity: onResume: 

2019-10-12 14:14:13.923 31496-31496/com.example.test E/MainActivity: onStop: 

由FirstActivity启动SecondActivity:

2019-10-12 14:14:43.623 31496-31496/com.example.test E/FirstActivity: onPause: 

2019-10-12 14:14:43.675 31496-31496/com.example.test E/SecondActivity: onCreate: --- SecondActivity

2019-10-12 14:14:43.678 31496-31496/com.example.test E/SecondActivity: onStart: 

2019-10-12 14:14:43.679 31496-31496/com.example.test E/SecondActivity: onResume: 

2019-10-12 14:14:44.024 31496-31496/com.example.test E/FirstActivity: onStop:

由SecondActivity启动ThirdActivity: 

2019-10-12 14:14:55.133 31496-31496/com.example.test E/SecondActivity: onPause: 

2019-10-12 14:14:55.186 31496-31496/com.example.test E/ThirdActivity: onCreate: --- ThirdActivity

2019-10-12 14:14:55.189 31496-31496/com.example.test E/ThirdActivity: onStart: 

2019-10-12 14:14:55.190 31496-31496/com.example.test E/ThirdActivity: onResume: 

2019-10-12 14:14:55.512 31496-31496/com.example.test E/SecondActivity: onStop: 

由ThirdActivity启动MainActivity:

2019-10-12 14:15:06.482 31496-31496/com.example.test E/FirstActivity: onDestroy: 

2019-10-12 14:15:06.491 31496-31496/com.example.test E/SecondActivity: onDestroy: 

2019-10-12 14:15:06.500 31496-31496/com.example.test E/ThirdActivity: onPause: 

2019-10-12 14:15:06.518 31496-31496/com.example.test E/MainActivity: onRestart: 

2019-10-12 14:15:06.518 31496-31496/com.example.test E/MainActivity: onStart: 

2019-10-12 14:15:06.519 31496-31496/com.example.test E/MainActivity: onResume: 

2019-10-12 14:15:06.818 31496-31496/com.example.test E/ThirdActivity: onStop: 

2019-10-12 14:15:06.819 31496-31496/com.example.test E/ThirdActivity: onDestroy: 

可以看出来,当由ThirdActivity启动MainActivity时,在该Task中位于MainActivity之上的所有Activity都被销毁,即所有在其上的Activity实例出栈,MainActivity此时处于栈顶被展示。

与SingleTop比较:

singleTop:栈顶不是我,我选择重生;

singleTask:栈顶不是我,我把骑在我头上的都干掉,然后我来做King。

适用场景:适合程序入口,其他Activity慎用,官网的文档是这么说的----make sure to test the usability of the activity during launch

singleInstance(全局复用模式)

我将SecondActivity启动模式设置为singleInstance,然后依次启动MainActivity >> FirstActivity >> SecondActivity >> ThirdActivity,打印各个Activity的TaskId如下:

2019-10-12 15:15:16.650 15052-15052/? E/MainActivity: onCreate:taskId == 9110

2019-10-12 15:15:21.421 15052-15052/com.example.test E/FirstActivity: onCreate:taskId == 9110

2019-10-12 15:15:23.937 15052-15052/com.example.test E/SecondActivity: onCreate:taskId == 9111

2019-10-12 15:15:27.010 15052-15052/com.example.test E/ThirdActivity: onCreate:taskId == 9110

发现 SecondActivity处于一个新的Task中,也就说 SecondActivity运行在一个独立的Task中,如果这个activity实例要启动一个新activity(比如示例代码中的ThirdActivity),那么新的Activity又会切换回主程序的Task。

我们再依次启动 MainActivity >> SecondActivity >> SecondActivity >> SecondActivity,日志打印如下:

2019-10-12 15:35:04.049 17751-17751/com.example.test E/MainActivity: onCreate: --- MainActivity

2019-10-12 15:35:04.050 17751-17751/com.example.test E/MainActivity: onCreate:taskId == 9125

2019-10-12 15:35:04.052 17751-17751/com.example.test E/MainActivity: onStart: 

2019-10-12 15:35:04.053 17751-17751/com.example.test E/MainActivity: onResume: 

2019-10-12 15:35:05.914 17751-17751/com.example.test E/MainActivity: onPause: 

2019-10-12 15:35:05.960 17751-17751/com.example.test E/SecondActivity: onCreate: --- SecondActivity

2019-10-12 15:35:05.960 17751-17751/com.example.test E/SecondActivity: onCreate:taskId == 9126

2019-10-12 15:35:05.962 17751-17751/com.example.test E/SecondActivity: onStart: 

2019-10-12 15:35:05.964 17751-17751/com.example.test E/SecondActivity: onResume: 

2019-10-12 15:35:06.343 17751-17751/com.example.test E/MainActivity: onStop: 

2019-10-12 15:35:07.395 17751-17751/com.example.test E/SecondActivity: onPause: 

2019-10-12 15:35:07.395 17751-17751/com.example.test E/SecondActivity: onNewIntent: 

2019-10-12 15:35:07.396 17751-17751/com.example.test E/SecondActivity: onResume: 

2019-10-12 15:35:10.777 17751-17751/com.example.test E/SecondActivity: onPause: 

2019-10-12 15:35:10.777 17751-17751/com.example.test E/SecondActivity: onNewIntent: 

2019-10-12 15:35:10.778 17751-17751/com.example.test E/SecondActivity: onResume: 

可以看得出来,如果用同样的 Intent再次启动这个activity,task会被调到前台,其 onNewIntent() 会被调用。

适用场景:适合需要与程序分离开的页面,比如闹钟的提示框,慎用~

本博文相关代码已提交到github:​​https://github.com/ZNKForSky/LaunchModeDemo​​,代码很简单,初学者如果实在看不懂,可以把代码下下来,结合代码去理解,也欢迎大家评论区与我交流~