本文主要是分析Activity各生命周期的变化,以及在不同启动模式下对生命周期的影响;
- Activity lifecycle
- Launch Mode
Intent flags
Handling affinities
分别有MainActivity、Main1Activity、Main2Activity三个activity(以下用0、1、2代替,默认启动模式)来进行测试;
adb shell dumpsys activity 查看当前activity堆栈信息
- Activity lifecycle
首先看android官方Activity-lifecycle concepts
1.1:正常启动一个activity按back键返回
可以看到新建了一个activity实例,先走了 onCreate -- onStart -- onResume启动0;
然后走onPause -- onStop -- onDestroy销毁0;
1.2:启动activity后按Home键
没有销毁Activity,然后重新开启
走了restart流程 onRestart -- onStart -- onResume
1.3:两个activity之间进行切换
新启动了1实例;0先走OnPuase,然后1走启动流程;
1走了onResume之后,0才走onStop,但还是没有销毁;
如果此时按Back键返回
0因为没有销毁所以走restart流程,当0可用之后(onResume),1走销毁流程;
总结:
activity的创建和销毁:OnCreat、OnDestory
activity可见和不可见:OnStart、OnStop
activity可用和不可用:OnResume,OnPause
activity不可见时开启:OnRestart
activity之间相互切换:0先走不可用(OnPause),1可用(OnResume)之后,0走不可见(OnStop)
back键会走销毁流程(OnDestory),Home键会走不可见流程(OnStop)
- Launch Mode
2.1 standard(默认模式)
默认值。系统在启动该 Activity 的task(任务)中创建 Activity 的新实例,并将 intent 传送给该实例。Activity 可以多次实例化,每个实例可以属于不同的task,一个task可以拥有多个实例。
2.1.1 依次开启activty 0-1-2-2
可以看到2创建了两次 不一样的实例,Task#218中也存在四个activity实例;
2.2 singleTop
如果当前任务的顶部已存在 Activity 的实例,则系统会通过调用其
onNewIntent()
方法来将 intent 转送给该实例,而不是创建 Activity 的新实例。Activity 可以多次实例化,每个实例可以属于不同的任务,一个任务可以拥有多个实例(但前提是返回堆栈顶部的 Activity 不是该 Activity 的现有实例)。2.2.1 2的启动模式改为singleTop,依次开启activty 0-1-2-2
2只创建了一次,第二次启动先走了OnPause,然后才走OnNewIntent;Task#220存在三个activity,由于没有重新走创建activity, 所以该启动模式为栈顶复用,但是要先走OnPause;
2.2.2 0的启动模式设置为singleTop,依次开启activty 0-1-2-0
如果不在task顶部,就会走标准模式;
2.3 singleTask
系统会创建新任务,并实例化新任务的根 Activity。但是,如果另外的任务中已存在该 Activity 的实例,则系统会通过调用其
onNewIntent()
方法将 intent 转送到该现有实例,而不是创建新实例。Activity 一次只能有一个实例存在。2.3.1 0的启动模式设置为singeTask 依次开启activty 0-1-2-0
0只创建了一次,第二次启动先走了OnNewIntent,然后进入reStart流程;
1和2都被销毁了,Task#224中只存在0这一个activity,所以该模式为栈内复用;
2.3.2 1的启动模式设置为singeTask 依次开启activty 0-1-2-1
这次在Task#230中存在0、1两个activity,说明singleTask模式在复用activity的时候销毁了在它之上的activity;
2.3.3 2的启动模式设置为singeTask 依次开启activty 0-1-2-2
2.4 singleInstance
与
"singleTask"
相似,唯一不同的是系统不会将任何其他 Activity 启动到包含该实例的任务中。该 Activity 始终是其任务唯一的成员;由该 Activity 启动的任何 Activity 都会在其他的任务中打开。2.4.1 2的启动模式设置为singeInstance 依次开启activty 0-1-2-2
2只创建了一次,第二次启动先走了OnPause,然后才进入OnNewIntent;
但0、1位于Task#236,2位于Task#237;
2.4.2 0的启动模式设置为singeInstance 依次开启activty 0-1-2-0
0只创建了一次,第二次启动先走了OnNewIntent,然后进入reStart流程;
所以该模式为单例模式,它独享一个Task;
总结:
standard:每次启动activity都重新创建实例,加入到当前Task中;
singleTop:栈顶复用,复用activity时走OnPause-OnNewIntent-OnResume;
singleTask:栈内复用,一个Task中只能存在一个该activity实例;复用activity时走OnNewIntent-OnRestart-OnStart-OnResume
singleInstance:全局复用,单例模式,系统中只存在一个该Activity实例;
复用流程:三种非标准模式当activity位于Task顶部时,重新启动自己都会先走OnPause,然后走OnNewIntent-OnResume;
如果activity不在Task顶部,另外两种启动模式在重新启动自己时;都会先走OnNewIntent,然后进入reStart流程;
- 3.Intent flags
启动activity时,可以通过在传递给startActivity()的意图中包含标志来修改activity与其Task的默认关联。
Intent intent = new Intent(MainActivity.this, Main1Activity.class); mContext.startActivity(intent.addFlags(Intent.XXX));
FLAG:FLAG_ACTIVITY_NEW_TASK,FLAG_ACTIVITY_SINGLE_TOP、 FLAG_ACTIVITY_CLEAR_TOP
3.1.1: 0通过startActivity启动1时添加该FLAG
1走创建流程,Task#245中存在0、1两个activity;
3.1.2 0先启动1,然后1启动0时添加FLAG
0走了两次创建流程,Task#246中也存在两个0的实例;
所以单独设置该FLAG没有任何作用;
3.2.1: 0先启动1,1再通过startActivity启动自己并添加该FLAG
从日志就可以看出该flag等同于singleTop;
3.3.1: 0先启动1,1通过该FLAG启动自己;
1启动了两次,但在第二个activity可用之后第一个走了销毁流程;
3.3.2:0先启动1,然后1通过该FLAG启动0;
Task#252中只有一个activity0,所以当Task中已经存在该activity,该FLAG的作用为清空在其之上的所有activity;
如果该activity为标准模式,会重新创建该实例后加入当前Task,其他模式则走复用流程;
- 4.Handling affinities
taskAffinity指示activity属于哪个Task。 默认情况下,同一应用程序中的所有activity都具有相互关联性。 因此,默认情况下,同一应用程序中的所有activity都希望属于同一Task。 但是,可以修改activity的默认affinity。 在不同应用程序中定义的activity可以共享affinity,或者可以在同一应用程序中定义的activity分配不同的Task affinity。
affinity在两种情况下起作用:1.startActivity时包含FLAG_ACTIVITY_NEW_TASK,2. activity的属性allowTaskReparenting为true;
4.1 taskAffinity+FLAG_ACTIVITY_NEW_TASK
1的taskAffinity为"com.task.one",0和2均为默认包名;
先从0启动1,然后依次执行1-->2-->1--->2--->1,其中2开启1的时候会添加FLAG_ACTIVITY_NEW_TASK
1开启了三次,第三次开启时没有反应,Task#277中有0、1、2,Task#278中有1、2
2在第一次开启1的时候配置了android:taskAffinity = "com.task.one"和FLAG_ACTIVITY_NEW_TASK;
第二次开启1系统会在配置了以上属性的Task中寻找对应的activity,找到了想复用,但没有对2做任何操作,所以无法成功复用;
4.2 taskAffinity+FLAG_ACTIVITY_NEW_TASK+FLAG_ACTIVITY_CLEAR_TOP
还是上面的流程,2开启1的时候会同时添加FLAG_ACTIVITY_NEW_TASK、FLAG_ACTIVITY_CLEAR_TOP
这一次可以看出1开启成功,Task中其他Activity跟单独使用FLAG_ACTIVITY_CLEAR_TOP一样