# AndroidLaunchModeTest
**Repository Path**: threekiloton/AndroidLaunchModeTest
## Basic Information
- **Project Name**: AndroidLaunchModeTest
- **Description**: android activity launch mode 测试
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2018-09-26
- **Last Updated**: 2020-12-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
```
public static void print (Activity activity) {
String taskAffinity = null;
try {
ActivityInfo activityInfo = activity.getPackageManager().getActivityInfo(
activity.getComponentName(),
PackageManager.GET_META_DATA
);
taskAffinity = activityInfo.taskAffinity;
} catch(NameNotFoundException e) {
e.printStackTrace();
}
Log.v(
"LaunchMode: ",
activity.getClass().getSimpleName() +
" taskId: " + activity.getTaskId() +
" affinity: " + taskAffinity +
" hash: " + activity.hashCode()
);
}
```
[彻底弄懂Activity四大启动模式 \- CSDN博客](https://blog.csdn.net/mynameishuangshuai/article/details/51491074)
[我打赌你一定没搞明白的Activity启动模式 \- 简书](https://www.jianshu.com/p/2a9fcf3c11e4)
[Android中Activity四种启动模式和taskAffinity属性详解 \- CSDN博客](https://blog.csdn.net/zhangjg_blog/article/details/10923643)
## android:taskAffinity
从概念上讲,具有相同亲和关系的 Activity 归属同一任务(从用户的角度来看,则是归属同一“应用”)。 任务的亲和关系由其根 Activity 的亲和关系确定。
## 启动 standard
> 系统始终会在目标任务中创建新的 Activity 实例并向其传送 Intent。
> 位于启动它的任务栈中,忽略taskAffinity
```
```
```
// 使用standard启动,可以看出 taskId 一致,位于同一个任务栈中
E/MainActivity: onCreate : MainActivity taskId: 26 affinity: tech.threekilogram.activitytasktest hash: 75967471
// 启动新的,创建新的实例
E/StandActivity: onCreate : StandActivity taskId: 26 affinity: .StandActivityTask hash: 102666220
// 再次启动新的,创建新实例
E/StandActivity: onCreate : StandActivity taskId: 26 affinity: .StandActivityTask hash: 64828334
```
## 启动singleTop
> 如果目标任务的顶部已存在一个 Activity 实例,则系统会通过调用该实例的 `onNewIntent()` 方法向其传送 Intent,而不是创建新的 Activity 实例。
> 位于启动它的Activity的任务栈中
```
E/LaunchMode:: StandActivity taskId: 24 affinity: .StandActivityTask hash: 90380303
// stand 启动一个singleTop Activity,位于启动它的任务栈中
E/SingleTopActivity: onCreate : 1 SingleTopActivity taskId: 24 affinity: .SingleTopActivityTask hash: 54123545
// 再次启动不会创建新的实例
E/SingleTopActivity: onNewIntent : 2 SingleTopActivity taskId: 24 affinity: .SingleTopActivityTask hash: 54123545
E/SingleTopActivity: onNewIntent : 3 SingleTopActivity taskId: 24 affinity: .SingleTopActivityTask hash: 54123545
```
### stand 和 singleTop 的 TaskAffinity
* standard和singleTop都是在原任务栈中新建Activity实例,不会启动新的task
#### 启动不同Affinity 的 stand mode activity
```
E/LaunchMode:: StandActivity taskId: 121 affinity: teck.threekilogram.activitylaunchtest hash: 178081170
// 虽然affinity不同,但是 taskID一致说明standard会进入启动它的 activity 的 task
E/StandAffinityActivity: onCreate:
E/LaunchMode:: StandAffinityActivity taskId: 121 affinity: standardActivity.affinity hash: 235085340
```
```
//single 同样,不会新建task,即使 taskAffinity 不一致
E/SingleTopActivity: onCreate
E/LaunchMode:: SingleTopActivity taskId: 123 affinity: teck.threekilogram.activitylaunchtest hash: 70843781
E/LaunchMode:: SingleTopAffinityActivity taskId: 123 affinity: .affinity.singleTop hash: 58682249
```
# SingleTask
> 栈内单一实例模式
> 如果没有指定taskAffinity,那么是默认的taskAffinity,启动时会加载到默认的任务栈中,如果指定了taskAffinity,将会新建任务栈,并且该Activity位于任务栈底,再次启动该activity回调onNewIntent
* 不指定taskAffinity
```
E/MainActivity: onCreate : MainActivity taskId: 34 affinity: tech.threekilogram.activitytasktest hash: 75967471
// 启动singleTask,因为没有指定taskAffinity,所以位于默认任务栈中
E/SingleTaskActivity: onCreate : SingleTaskActivity taskId: 34 affinity: tech.threekilogram.activitytasktest hash: 35514606
// singgletask 启动一个standard activity,stand会位于启动它的任务栈中
E/StandActivity: onCreate : StandActivity taskId: 34 affinity: .StandActivityTask hash: 18942361
// 再次启动singleTask,弹出之前的standard,回调onNewIntent
E/SingleTaskActivity: onNewIntent : 1 SingleTaskActivity taskId: 34 affinity: tech.threekilogram.activitytasktest hash: 35514606
```
* 指定taskAffinity
```
```
```
E/MainActivity: onCreate : MainActivity taskId: 35 affinity: tech.threekilogram.activitytasktest hash: 246038114
// 启动 SingleTask 模式的activity 因为taskAffinity不同,所以新创建任务栈,并且位于栈底
E/SingleTaskActivity: onCreate : SingleTaskActivity taskId: 37 affinity: .SingleTaskActivityTask hash: 205766038
```
> 在最近应用列表里会出现两个任务栈列表

* singleTask启动 stand/singleTop
```
E/SingleTaskActivity: onCreate : SingleTaskActivity taskId: 42 affinity: .SingleTaskActivityTask hash: 154989292
// 启动standard,位于singleTask任务栈
E/StandActivity: onCreate : StandActivity taskId: 42 affinity: .StandActivityTask hash: 116514478
// 再次启动singleTask
E/SingleTaskActivity: onNewIntent : 1 SingleTaskActivity taskId: 42 affinity: .SingleTaskActivityTask hash: 154989292
// 启动singleTop
E/SingleTopActivity: onCreate : 1 SingleTopActivity taskId: 42 affinity: .SingleTopActivityTask hash: 222307071
// 再次启动singleTask
E/SingleTaskActivity: onNewIntent : 2 SingleTaskActivity taskId: 42 affinity: .SingleTaskActivityTask hash: 154989292
```
### SingleTask Affinity
如果指定了singleTask Activity 的affinity 那么他启动的时候会去寻找该 task, 如果存在该task,在该task中寻找该activity,如果activity存在,activity之前的activity全部弹出如果不存在那么新建activity
```
E/LaunchMode:: MainActivity taskId: 129 affinity: teck.threekilogram.activitylaunchtest hash: 183960631
//main 启动 singleTask activity,该activity指定了taskAffinity,所以新建task,并把activity压入
E/SingleTaskActivity: onCreate :
E/LaunchMode:: SingleTaskAffinityActivity taskId: 133 affinity: .singleTaskAffinity hash: 188990465
//single task activity 启动 stand activity ,那么新启动的activity和single task 同一个task
E/LaunchMode:: MainActivity taskId: 133 affinity: teck.threekilogram.activitylaunchtest hash: 190397367
//再次启动 singleTask activity 弹出前面的activity
E/SingleTaskActivity: onNewIntent :
E/LaunchMode:: SingleTaskAffinityActivity taskId: 134 affinity: .singleTaskAffinity hash: 40139088
```
#### 不同的task之间切换
已知: mainActivity : stand launchMode,没有指定affinity
SingleTaskActivity : singleTask launchMode 没有指定affinity
SingleTaskAffinityActivity : singleTask launchMode, 指定了affinity
```
1 使用 main 启动 SingleTaskAffinityActivity
task 01
SingleTaskAffinityActivity
task 00
main
2 SingleTaskAffinityActivity 启动 main
task 01
main
SingleTaskAffinityActivity
task 00
main
3 main 启动 SingleTaskActivity 注意:SingleTaskActivity 和 main 具有相同的affinity
task 00
SingleTaskActivity
main
task 01
main
SingleTaskAffinityActivity
4 通过返回键不断退出
SingleTaskActivity(task 00) --> main(task 00)--> main(task 01) --> SingleTaskAffinityActivity(task 01)
和启动顺序不一致
main --> SingleTaskAffinityActivity --> main --> SingleTaskActivity
这是因为在task之间切换的时候会将task整体移到前台,所以启动SingleTaskActivity的时候会将根部的main所属的task带到前台
```
# singleInstance
全局实例模式(单独占据一个任务栈,任何其他的activity都不可以进入,及时有相同的taskAffinity)
该activity 会位于单一的task中
```
E/MainActivity: onCreate : MainActivity taskId: 44 affinity: tech.threekilogram.activitytasktest hash: 75967471
// 启动singleInstance
E/SingleInstanceActivity: onCreate : SingleInstanceActivity taskId: 45 affinity: tech.threekilogram.activitytasktest hash: 93853216
```
* 启动没有taskAffinity的stand/singleTop activity
```
E/MainActivity: onCreate : MainActivity taskId: 47 affinity: tech.threekilogram.activitytasktest hash: 75967471
// 启动singleInstance新建任务栈
E/SingleInstanceActivity: onCreate : SingleInstanceActivity taskId: 48 affinity: tech.threekilogram.activitytasktest hash: 93853216
// 再次启动一个没有taskAffinity的standActivity,会加载到默认任务栈
E/StandActivity: onCreate : StandActivity taskId: 47 affinity: tech.threekilogram.activitytasktest hash: 232965136
```
* 启动有taskAffinity的stand/singleTop activity
```
E/MainActivity: onCreate : MainActivity taskId: 54 affinity: tech.threekilogram.activitytasktest hash: 256947076
// 启动singleInstance新建任务栈
E/SingleInstanceActivity: onCreate : SingleInstanceActivity taskId: 58 affinity: tech.threekilogram.activitytasktest hash: 100743098
// 启动一个有taskAffinity的standActivity,先创建任务栈,之后入栈
E/StandActivity: onCreate : StandActivity taskId: 59 affinity: .StandActivityTask hash: 120169912
```
# Intent与启动模式相关的Flag简介
## **FLAG_ACTIVITY_NEW_TASK**
* 它与launchMode="singleTask"具有相同的行为。实际上,并不是完全相同!
很少单独使用FLAG_ACTIVITY_NEW_TASK,通常与FLAG_ACTIVITY_CLEAR_TASK或FLAG_ACTIVITY_CLEAR_TOP联合使用
使用该标记启动新的activity,将会新建task(根据taskAffinity),该activity位于栈底,同时历史记录出现两个task

## **FLAG_ACTIVITY_SINGLE_TOP**
* 它与launchMode="singleTop"具有相同的行为。实际上,的确如此!

## **FLAG_ACTIVITY_CLEAR_TOP**
* 清除"包含Activity的task"中位于该Activity实例之上的其他Activity实例。
* FLAG_ACTIVITY_CLEAR_TOP和FLAG_ACTIVITY_NEW_TASK两者同时使用,就能达到和launchMode="singleTask"一样的效果!

## **FLAG_ACTIVITY_CLEAR_TASK**
* 清除栈内所有Activity,(回调onDestroy),然后新建该Activity置于栈底
```
Intent intent = new Intent( this, MainActivity.class );
intent.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK );
startActivity( intent );
```
```
E/MainActivity: onDestroy : tech.threekilogram.activitytasktest.MainActivity@5d2c24e
E/MainActivity: onCreate : MainActivity taskId: 97 affinity: tech.threekilogram.activitytasktest hash: 159184609
```
> **当同时使用launchMode和上面的FLAG_ACTIVITY_NEW_TASK等标签时,以FLAG_ACTIVITY_NEW_TASK为标准。也就是说,代码的优先级比manifest中配置文件的优先级更高**!