Activity的生命周期和启动模式

1.Activity的生命周期

a.典型情况下的生命周期

Activity启动—>onCreate—>onStart—>onResume—>onPause—>onStop—>onDestroy

onStop后重新启动则要先调onRestart再调onStart
其中,onStart,onStop和onResume,onPause看起来差不多,甚至大多数情况下保留一对即可,但实际上这两组回调代表的意义不同。onStart,onStop是从Activity是否可见这个角度来回调的,而onResume,onPause是从Activity是否在前台这个角度来回调的。

b.异常情况下的生命周期

1.资源相关的系统配置发生改变导致Activity被杀死并重新创建
比如在默认情况下,横竖屏切换就会导致Activity被杀死并重新创建。在这种情况下生命周期如下:
Activity—>onSaveInstanceState—>onDestroy
在该周期中onSaveInstaceState保存数据又用于创建新的Activity,并传到新的Activity的onCreate方法中,而后会调用onRestoreInstanceState还原之前保存的数据。

onSaveInstanceState和onRestoreInstanceState只会在异常情况下,并且是杀死Activity后自动重新创建Activity的情况下会被调用。保存数据的流程如下:Activity会调用onSaveInstanceState去保存数据,然后Activity会委托Window去保存数据,Window会委托它的顶级容器去保存数据。顶级容器通常是DecorView。最后顶级容器一一通知子View去保存数据。View中有onSaveInstanceState和onRestoreInstanceState方法保存数据。如TextView中保存了自己的文本选中状态和文本内容。

2.资源内存不足导致低优先级的Activity被杀死
Activity按照优先级从高到低可分为如下三种:
a.前台Activity,正在和用户交互的Activity
b.可见但非前台的Activity,比如Activity中弹了一个对话框,导致Activity可见但是位于后台无法和用户直接交互。
c.后台Activity,已经被暂停的Activity,比如执行了onStop,优先级最低。
当系统内存不足时系统就会按照上述优先级去杀死目标Activity。

2.Activity的启动模式

目前有四种启动模式:standard、singleTop、singleTask、singleInstance

standard:标准模式

这也是系统的默认模式。每次启动一个Activity都会重新建一个新的实例,不管这个实例是否已经存在。在这种模式下,谁启动了这个Activity,这个Activity就运行在启动它的那个Activity所在的栈中。正因为这个机制,所以当使用ApplicationContext去启动Activity时会报错。这是因为standard模式的Activity默认会进入启动它的Activity所属的任务栈中,但是非Activity类型的Context并没有所谓的任务栈,所以会出错

singleTop:栈顶复用模式

在这种模式下,当新Activity已经有一个实例存在于任务栈的栈顶,那么此Activity不会被重新创建。举个例子,当栈内情况为ABCD,如果D的启动模式为singleTop,那么栈内的情况仍然是ABCD;如果D的启动模式为standard,那么D被重新创建,栈内为ABCDD;

singleTask:栈内复用模式

这种模式下,只要Activity在一个栈中存在,那么多次启动Activity都不会重新创建实例。具体流程是:当一个Activity请求启动后,比如ActivityA,系统会首先寻找是否存在A想要的任务栈,如果不存在,就创建一个任务栈。如果存在A想要的任务栈,就要看是否在栈中有A的实例存在。如果实例存在,则把A调到栈顶,并清除原本位于A上的其他Activity。

情况一:目前有任务栈S1,栈内情况为ABC。这个时候D以singleTask模式请求启动,所需任务栈为S2。由于S2和D均不存在实例,那么此时会创建S2任务栈,并创建D
情况二:任务栈S1情况为ABC,D以singleTask模式请求启动,所需任务栈为S1,此时系统会直接创建D的实例并将其入栈到S1
情况三:任务栈S1情况为ADBC,此时要启动D,根据栈内复用原则,此时会将BC出栈。最终S1的情况为AD

这里的Activity所需的任务栈指的是Activity的TaskAffinity参数。在AndroidManifest中可以指定。如:

<activity
    android:name="com.zxx.SecondActivity
    android:taskAffinity="com.zxx.task"
    android:launchMode="singleTask"/>

taskAffinity属性值为字符串,中间必须包含”.”。当没有设置taskAffinity时,默认为包名

singleInstance:单实例模式

这是一种加强的singleTask模式。它除了具有singleTask模式的所有特性外,还加强了一点就是Activity只能单独地位于一个任务栈中。

特殊情况:
假设目前有两个任务栈,前台任务栈情况为AB,后台任务栈情况为CD.假设CD的启动模式为singleTask.现在请求D,那么整个后台任务栈都会被切换到前台。这个时候按back键,顺序为DCBA

小技巧:观察任务栈的命令:adb shell dumpsys activity

你可能感兴趣的:(android学习)