1.Activity栈的基本实现原理:
启动Activity时,系统会寻找Activity对应的栈,如果没有,创建一个栈,创建Activity实例压入栈中,如果有,判断是否已经有这个实例。如果有,还会根据我们设定好的启动模式进行处理,如果没有则创建实例,并按照先进后出的原则一一放入任务栈中,当我们按back键时,就会有一个activity从任务栈顶移除,重复下去,直到任务栈为空,系统就会回收这个任务栈。
影响启动模式的有一个taskAffinity属性,可以简单的理解为任务相关性。
- 这个参数标识了一个Activity所需任务栈的名字,默认情况下,所有Activity所需的任务栈的名字为应用的包名
- 我们可以单独指定每一个Activity的taskAffinity属性覆盖默认值
- 一个任务的affinity决定于这个任务的根activity(root activity)的taskAffinity
- 在概念上,具有相同的affinity的activity(即设置了相同taskAffinity属性的activity)属于同一个任务
- 为一个activity的taskAffinity设置一个空字符串,表明这个activity不属于任何task
指定方式如下:
<activity android:name=".ActivitySingleTop" android:launchMode="singleTop" android:taskAffinity="com.castiel.demo.singletop"/>
2.Activity的启动模式
分为:
standard、singleTop、singleTask、singleInstance
3.设置启动模式
4.standard模式:标准
标准模式,是系统默认的启动模式。系统每次启动一个Activity都会重写创建一个新的实例,不管这个实例存不存在。一个任务栈可以有多个实例,每个实例也可以属于不同任务栈,哪个任务栈启动了Activity,这个Activity就在哪个任务栈中。Activity的生命周期回调方法也正常调用。由于是默认,launchMode属性可以不设置。
<activity android:name="com.sean.zq.android.view.activity.LaunchStandardActivity"
android:launchMode="standard"/>
11-11 19:05:02.591 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: ********onCreate()方法**********
11-11 19:05:02.592 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: onCreate:LaunchStandardActivity TaskId: 29390 hasCode:71583758
11-11 19:05:02.593 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: taskAffinity:com.sean.zq.android
11-11 19:05:07.741 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: ********onCreate()方法**********
11-11 19:05:07.742 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: onCreate:LaunchStandardActivity TaskId: 29390 hasCode:213492731
11-11 19:05:07.743 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: taskAffinity:com.sean.zq.android
5.SingleTop模式:栈顶复用
该模式下,如果目标Activity已经位于栈顶,就不会继续创建该Activity的新实例,同时它的onNewIntent方法会被调用,使用这个方法中的形参,我们可以获取到当前请求的信息。如果栈顶不存在该Activity的实例,则情况与standard模式相同。需要注意的是这个Activity它的onCreate(),onStart()方法不会被调用,因为它并没有发生改变。
下面的这段日志表示了当目标Activity,没有在栈顶的情况下,可以看出和standard模式是一样的。
一个栈内:ABCA
11-11 19:05:02.591 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: ********onCreate()方法**********
11-11 19:05:02.592 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: onCreate:LaunchStandardActivity TaskId: 29390 hasCode:71583758
11-11 19:05:02.593 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: taskAffinity:com.sean.zq.android
11-11 19:05:07.741 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: ********onCreate()方法**********
11-11 19:05:07.742 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: onCreate:LaunchStandardActivity TaskId: 29390 hasCode:213492731
11-11 19:05:07.743 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: taskAffinity:com.sean.zq.android
11-11 19:07:23.766 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: ********onCreate()方法**********
11-11 19:07:23.767 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: onCreate:LaunchSingleTopActivity TaskId: 29390 hasCode:237496541
11-11 19:07:23.768 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: taskAffinity:com.sean.zq.android
11-11 19:07:23.798 7850-7871/com.sean.zq.android I/zygote64: Compiler allocated 4MB to compile void android.view.View.<init>(android.content.Context, android.util.AttributeSet, int, int)
11-11 19:07:31.370 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: ********onCreate()方法**********
11-11 19:07:31.370 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: onCreate:LaunchStandardActivity TaskId: 29390 hasCode:50754318
11-11 19:07:31.371 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: taskAffinity:com.sean.zq.android
11-11 19:07:39.355 7850-7871/com.sean.zq.android I/zygote64: Do full code cache collection, code=498KB, data=337KB
11-11 19:07:39.355 7850-7871/com.sean.zq.android I/zygote64: After code cache collection, code=496KB, data=296KB
11-11 19:07:39.376 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: ********onCreate()方法**********
11-11 19:07:39.377 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: onCreate:LaunchSingleTopActivity TaskId: 29390 hasCode:213558011
11-11 19:07:39.377 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: taskAffinity:com.sean.zq.android
11-11 19:19:36.152 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: ********onCreate()方法**********
11-11 19:19:36.153 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: onCreate:LaunchStandardActivity TaskId: 29390 hasCode:121438806
11-11 19:19:36.154 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: taskAffinity:com.sean.zq.android
11-11 19:19:40.013 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: ********onCreate()方法**********
11-11 19:19:40.013 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: onCreate:LaunchSingleTopActivity TaskId: 29390 hasCode:56805667
11-11 19:19:40.014 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: taskAffinity:com.sean.zq.android
11-11 19:19:49.874 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: ********onNewIntent()方法*********
11-11 19:19:49.875 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: onNewIntent:LaunchSingleTopActivity TaskId: 29390 hasCode:56805667
11-11 19:19:49.876 7850-7850/com.sean.zq.android I/com.sean.zq.android.view.activity.LaunchModeBaseActivity: taskAffinity:com.sean.zq.android
上面的这段日志表示了当目标Activity,在栈顶的情况下,不仅没有创建新实例,还调用了onNewIntent()方法。
如果这个时候的跳转流程是ABCC的话,那么一个栈内:ABC
singleTop的两种情况:
1.当前栈中已有该Activity的实例并且该实例位于栈顶时,不会新建实例,而是复用栈顶的实例,并且会将Intent对象传入,回调onNewIntent方法
2.当前栈中不存在该Activity的实例或已有该Activity的实例但不在栈顶时,其行为和standard启动模式一样
很重要的一点taskAffinity属性不对standard和singleTop模式有任何影响,即时你指定了该属性为其他不同的值,这两种启动模式下不会创建新的task(如果不指定即默认值,即包名)
6. SingleTask模式:栈内复用
这是一个栈内单实例的模式,有各式各样的组合, 十分复杂。在这个模式下,如果栈中存在这个Activity的实例就会复用这个Activity,不管它是否位于栈顶,复用时,会将它上面的Activity全部出栈,并且会回调该实例的onNewIntent方法。其实这个过程还存在一个任务栈的匹配,因为这个模式启动时,会在自己需要的任务栈中寻找实例,这个任务栈就是通过taskAffinity属性指定。如果这个任务栈不存在,则会创建这个任务栈。