Activity有四种启动模式,分别是standard
、singleTop
、singleTask
、singleInstance
,如果不指定则默认是standard模式。
如果没有指定启动模式的话,默认会使用standard
模式,这种模式下启动Activity,无论任务栈中是否已经有同类型的Activity实例,系统都会创建一个新的实例。
如果任务栈中已经有相同类型的Activity实例,并且位于栈顶,则不会重新创建新的实例,通过onNewIntent传递新的Intent,否则会创建新的Activity实例。
如果任务栈中已经有相同类型的Activity实例,无论是否位于栈顶,都不会创建新的实例,通过onNewIntent传递新的Intent,如果不是位于栈顶,则将其示例顶部的Activity全部销毁,如果任务栈中没有则创建新的Activity实例。
如果任务栈中已经有相同类型的Activity实例,就不会创建新的实例,通过onNewIntent传递新的Intent,如果任务栈中没有则创建新的任务栈和实例,并且该任务栈只存放该Activity。
其实上面的说明还不够精确,因为除了launchMode会影响这些行为,还有FLAG_ACTIVITY_*和taskAffinity等参数也会影响,下面就用一些示例来验证下各种不同的情况启动Activity的行为,文章末尾会附上整个示例项目。
我们使用测试集合1
来进行测试,test1、test2都是standard模式,首先按照test1
->test2
顺序依次启动,此时再启动test1,会发现任务栈变成
test1
->test2
->test1
完整的日志如下:
D/LaunchMode: taskId: 2349, name: Test1, ref: TestActivity1@94282aa onCreate
D/LaunchMode: taskId: 2349, name: Test2, ref: TestActivity2@8516e9 onCreate
D/LaunchMode: taskId: 2349, name: Test2, ref: TestActivity2@c1d0baf onCreate
可以看出,当前栈中已经存在test2了,但是还是创建了一个新的test2实例。
我们使用测试集合1
来进行测试,test1、test2是standard模式,test3是singleTop模式,首先按照test1
->test2
顺序依次启动,此时启动test3,会发现任务栈变成
任务栈一:test1
->test2
->test3
此时再启动test3,发现任务栈仍然是
任务栈一:test1
->test2
->test3
此时再启动test2,发现任务栈变成
任务栈一:test1
->test2
->test3
->test2
此时再启动test3,发现任务栈变成
任务栈一:test1
->test2
->test3(1)
->test2
->test3(2)
完整的日志如下:
D/LaunchMode: taskId: 2349, name: Test1, ref: TestActivity1@c227ac onCreate
D/LaunchMode: taskId: 2349, name: Test2, ref: TestActivity2@a0984cc onCreate
D/LaunchMode: taskId: 2349, name: Test3, ref: TestActivity3@7de23bb onCreate
D/LaunchMode: taskId: 2349, name: Test3, ref: TestActivity3@7de23bb onNewIntent
D/LaunchMode: taskId: 2349, name: Test2, ref: TestActivity2@9bcd30e onCreate
D/LaunchMode: taskId: 2349, name: Test3, ref: TestActivity3@20b885c onCreate
可以看出,当前栈中不存在test3时,会在当前任务栈中创建一个新的test3实例,当任务栈中已经有test3实例并且处于栈顶时,则不会再创建新的test3实例,如果任务栈中存在test3实例,但是不在栈顶时,仍然会创建新的test3实例。
我们使用测试集合1
来进行测试,test1、test2是standard模式,test4是singleTask模式,首先按照test1
->test2
顺序依次启动,此时启动test4,会发现任务栈变成
任务栈一:test1
->test2
->test4
此时再启动test4,发现任务栈仍然是
任务栈一:test1
->test2
->test4
此时再启动test2,发现任务栈变成
任务栈一:test1
->test2
->test4
->test2
此时再启动test4,发现任务栈变成
任务栈一:test1
->test2
->test4
完整的日志如下:
D/LaunchMode: taskId: 2350, name: Test1, ref: TestActivity1@5c9e97f onCreate
D/LaunchMode: taskId: 2350, name: Test2, ref: TestActivity2@99438d2 onCreate
D/LaunchMode: taskId: 2350, name: Test4, ref: TestActivity4@80f5269 onCreate
D/LaunchMode: taskId: 2350, name: Test4, ref: TestActivity4@80f5269 onNewIntent
D/LaunchMode: taskId: 2350, name: Test2, ref: TestActivity2@fb38e04 onCreate
D/LaunchMode: taskId: 2350, name: Test4, ref: TestActivity4@80f5269 onNewIntent
D/LaunchMode: taskId: 2350, name: Test2, ref: TestActivity2@fb38e04 onDestroy
可以看出,当前栈中不存在test4时,会在当前任务栈中创建一个新的test4实例,当任务栈中已经有test4实例,则不会再创建新的test4实例,如果test4不在栈顶,则会将栈顶的activity全部销毁。
我们使用测试集合1
来进行测试,test1、test2是standard模式,test5是singleInstance模式,首先按照test1
->test2
顺序依次启动,此时启动test5,会发现任务栈变成
任务栈一:test1
->test2
任务栈二:test5
test5是单独一个任务栈,此时再启动test1会发现任务栈变成
任务栈一:test1
->test2
->test1
任务栈二:test5
此时再启动test5会发现任务栈仍然是
任务栈一:test1
->test2
->test1
任务栈二:test5
完整的日志如下:
D/LaunchMode: taskId: 2354, name: Test1, ref: TestActivity1@89f7f7b onCreate
D/LaunchMode: taskId: 2354, name: Test2, ref: TestActivity2@3242971 onCreate
D/LaunchMode: taskId: 2355, name: Test5, ref: TestActivity5@dac8757 onCreate
D/LaunchMode: taskId: 2354, name: Test1, ref: TestActivity1@18df2ad onCreate
D/LaunchMode: taskId: 2355, name: Test5, ref: TestActivity5@dac8757 onNewIntent
可以看出,当test5实例不存在时,会新启动一个任务栈和test5实例,并且新的任务栈中只会存放test5,如果test5实例已经存在,则不会创建新的实例。
我们使用测试集合2
来进行测试,test1、test2是standard模式,test3是singleTask模式,另外test3的taskAffinity设置为.Test3,首先按照test1
->test2
顺序依次启动,此时启动test3,会发现任务栈变成
任务栈一:test1
->test2
任务栈二:test3
test3是单独一个任务栈,此时再启动test1会发现任务栈变成
任务栈一:test1
->test2
任务栈二:test3
->test1
此时再启动test3会发现任务栈会变成
任务栈一:test1
->test2
任务栈二:test3
完整的日志如下:
D/LaunchMode: taskId: 2358, name: Test1, ref: TestActivity1@b53f903 onCreate
D/LaunchMode: taskId: 2358, name: Test2, ref: TestActivity2@1613a00 onCreate
D/LaunchMode: taskId: 2359, name: Test3, ref: TestActivity3@6c8315f onCreate
D/LaunchMode: taskId: 2359, name: Test1, ref: TestActivity1@aec8ff5 onCreate
D/LaunchMode: taskId: 2359, name: Test3, ref: TestActivity3@6c8315f onNewIntent
D/LaunchMode: taskId: 2359, name: Test1, ref: TestActivity1@aec8ff5 onDestroy
可以看出,当test3实例不存在时,会新启动一个任务栈和test3实例,这是因为我们为test3配置了taskAffinity=.Test3,它会去查找与taskAffinity关联的任务栈,没有找到,所以会创建一个新的任务栈并且与taskAffinity关联,然后将test3实例存放到这个任务栈中,如果已经存在则根据singleTask模式的规则处理。
我们使用测试集合3
来进行测试,test1、test2、test3是standard模式,另外test3的taskAffinity设置为.Test3,首先按照test1
->test2
顺序依次启动,此时设置FLAG_ACTIVITY_NEW_TASK标志启动test3,会发现任务栈变成
任务栈一:test1
->test2
任务栈二:test3
test3是单独一个任务栈,此时再启动test1会发现任务栈变成
任务栈一:test1
->test2
任务栈二:test3
->test1
此时再设置FLAG_ACTIVITY_NEW_TASK标志启动test3会发现任务栈没有变化
任务栈一:test1
->test2
任务栈二:test3
->test1
不仅任务栈没有变化,而且test3也没有恢复到栈顶来。
完整的日志如下:
D/LaunchMode: taskId: 2407, name: Test1, ref: TestActivity1@5c9e97f onCreate
D/LaunchMode: taskId: 2407, name: Test2, ref: TestActivity2@5b87a82 onCreate
D/LaunchMode: taskId: 2408, name: Test3, ref: TestActivity3@8323949 onCreate
D/LaunchMode: taskId: 2408, name: Test1, ref: TestActivity1@14ba6ef onCreate
可以看出,设置FLAG_ACTIVITY_NEW_TASK标志和singleTask模式启动还是有一些区别,在test3已经启动的条件下,再次通过设置FLAG_ACTIVITY_NEW_TASK标志启动test3,此时不仅不会把test3恢复到栈顶,甚至连onNewIntent也没回调。
文件 | 大小 | 修改时间 |
---|---|---|
app | 2022年03月31日 | |
build.gradle | 358 B | 2022年03月30日 |
gradle/wrapper | 2022年03月30日 | |
gradle.properties | 1 kB | 2022年03月30日 |
gradlew | 6 kB | 2022年03月30日 |
gradlew.bat | 3 kB | 2022年03月30日 |
local.properties | 437 B | 2022年03月30日 |
settings.gradle | 327 B | 2022年03月30日 |