先对Activity、Intent、返回栈、Activity的状态以及生命周期了解一下。
Activity启动模式分为四种:standard、singleTop、singleTask、singleInstance,可以在 AndroidManifest.xml中的 activity标签中设置,下面一一讲解。
standard(标准启动模式)
标准模式是默认的启动模式,可以不用在清单文件中指定,它的特点就是每次启动都会创建一个新的Activity实例,那么启动三次就要点三次Back键才能退回到主界面。这个模式很简单,不再赘述~
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,代码很简单,初学者如果实在看不懂,可以把代码下下来,结合代码去理解,也欢迎大家评论区与我交流~