天天看点

Activity的生命周期和启动模式详解

    • 1Activity生命周期全面分析
      • 1-1典型情况下正常情况下的生命周期分析
      • 1-2异常情况下的生命周期分析
        • 1-2-1资源相关的系统配置发生改变导致Activity重建
        • 1-2-2内存不足导致低优先级的Activity被杀死
    • 2Activity的启动模式
      • 2-1Activity的LaunchMode

1Activity生命周期全面分析

1-1典型情况下(正常情况下)的生命周期分析

Activity的生命周期和启动模式详解

(1)onCreate表示Activity 正在被创建,我们可以在这个方法中做一些初始化工作;

(2)onStart表示Activity 正在被启动,此时Activity已经显示出来了,但是还未出现在前台,用户还看不见,还不能与它进行交互;

(3)onResume表示Activity 已经出现在前台,此时可以与用户进行交互;

(4)onPause表示Activity 正在停止,但是此时还处在可见状态,此时可以做一些不太耗时的工作,如:停止动画,否则会影响新界面的显示;

(5)onStop表示Activity 即将停止,可以做一些稍微重量级的回收工作,但是也不能太耗时;

(6)onDestory表示Activity 即将被销毁,可以做一些回收工作和最终的资源释放;

(7)onRestart表示Activity 正在重新启动,一般情况下,当前Activity从不可见状态变为可见状态时被调用;

(8)从Activity是否可见来说,onStart和onStop是配对的,从Activity是否出现在前台来说,onResume和onPause是配对的;

注意:图中从onStop->onCreate这条路径,可能猛的一看,看的会有点懵逼,那我们就一起来分析一下在这中间Activity究竟经历了什么,平时如果手机内存不够时,会自动终止后台存在的进程,因为已经执行了onStop方法,那么该Activity肯定是处于后台的,如果接下来手机内存不够前台的进程使用了,就会从后台进程中选择优先级比较低的进程来进行内存释放,一旦内存释放那么该进程就会立即终止,Activity将不会在执行onDestroy方法,如果这时,用户从快捷启动栏,又重新启动了该应用,那么该Activity将会再次执行onCreate方法

从ActivityA启动ActivityB,中间Activity的生命周期执行顺序:

A:onPause->B:onCreate->B:onStart->B:onResume->A:onStop

1-2异常情况下的生命周期分析

1-2-1资源相关的系统配置发生改变导致Activity重建

典型的情况是手机屏幕的横竖屏变化,接下来我们就来一起来看一下在手机横竖屏切换时,Activity的生命周期执行顺序:

onPause->onSaveInstanceState->onStop->onDestroy->onCreate->onStart->onRestoreInstanceState->onResume

从打印的日志看来,横屏和竖屏Android系统会加载不同的系统资源,导致产生旧Activity的销毁,以及新Activity的重建,又因为两个Activity之间是存在联系的,这种联系通过onSaveInstanceState和onRestoreInstanceState方法建立,onSaveInstanceState用于保存旧Activity当前有用的信息,onRestoreInstanceState用于在新Activity中恢复旧Activity中某些有用的信息;

接下来看一下,onSaveInstanceState和onRestoreInstanceState方法的执行时机,先来说一下onSaveInstanceState,在下列情况下会执行onSaveInstanceState:

1、当用户按下HOME键时。

这是显而易见的,系统不知道你按下HOME后要运行多少其他的程序,自然也不知道activity A是否会被销毁,故系统会调用onSaveInstanceState,让用户有机会保存某些非永久性的数据。以下几种情况的分析都遵循该原则

2、长按HOME键,选择运行其他的程序时。

3、按下电源按键(关闭屏幕显示)时。

4、从activity A中启动一个新的activity时。

5、屏幕方向切换时,例如从竖屏切换到横屏时。

总而言之,就是存在非人为意愿由系统自动销毁Activity的可能性时会执行onSaveInstanceState,注意是存在可能性,但是不一定发生。

接下来看onRestoreInstanceState方法,该方法是当你的Activity确实被异常终止然后重建Activity时会执行。

注:onSaveInstanceState执行在onStop之前,onRestoreInstanceState执行在onStart之后,而且两者不一定成对出现,只有Activity确实发生了销毁重建时,才会成对出现,官方建议采用onRestoreInstanceState去恢复数据。

保存和恢复View层次结构的系统工作流程:Activity被异常终止时,会调用onSaveInstanceState去保存数据,然后Activity会委托Window去保存数据,接着Window再委托它上面的顶层容器(一般为DecorView)去保存数据,最后顶层容器再一一通知它的子元素来保存数据,这样整个过程就结束了。

1-2-2内存不足导致低优先级的Activity被杀死

Activity的优先级分类:

  1.前台Activity,可以与用户进行交互的Activity的具有最高的优先级;

  2.可见但非前台Activity,无法直接与用户进行交互,优先级次之;

  3.后台Activity,执行了onStop方法的Activity,优先级最低;

当系统内存不足时,会按照优先级去杀死Activity的所在进程。

2Activity的启动模式

2-1Activity的LaunchMode

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

(1)standard:标准模式,是系统的默认模式,每次启动一个新的Activity都会创建一个新的实例,不管这个实例是否已经存在,一个任务栈可以有多个实例,每个实例也可以属于不同的任务栈,该模式的Activity会默认进入启动它的Activity所属的任务栈,所以当以ApplicationContext作为上下文传入时,会发生错误;

(2)singleTop:栈顶复用模式,在这种模式下,如果新的Activity已经位于任务栈的栈顶,那么此Activity不会被重新创建,同时它的onNewIntent方法会被回调,通过此方法的参数可以取出当前请求的信息。

如果接下来要启动的Activity位于任务栈栈顶,接下来Activity的生命周期执行过程为:onPause->onNewIntent->onResume

如果接下来要启动的Activity没有位于栈顶,接下来Activity的生命周期执行过程为:onPause->onCreate->onStart->onResume->onSaveInstanceState->onStop

(3)singleTask:栈内复用模式,这是一种单实例模式,在这种模式下,只要Activity在一个栈中存在,那么多次启动该Activity都不会重新创建实例,它的onNewIntent方法也会被回调,执行过程为:

  先查找是否存在该活动想要的任务栈,

    如果没有,就重新创建一个任务栈,然后创建该活动的实例把该活动放入栈中,

    如果存在这样的任务栈,则查看该任务栈内是否存在该Activity的实例,     

      如果存在该实例,就把该活动调到栈顶,将该活动上的其他活动都出栈,

      如果不存在该实例,创建一个该活动的实例,将其放入该任务栈

(4)singleInstance:单实例模式,这是一种加强的singleTask模式,具有该模式的Activity只能单独的位于一个任务栈中。

给Activity指定启动模式的方式:

  一、通过AndroidManifest为Activity指定launchMode属性,例如:

  <activity     android:name=".TestRecycleActivity"     android:launchMode="singleTop"    />

  二、通过给Intent添加标志位来实现,例如:

  Intent i = new Intent();   i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

两种方式的区别:第二种方式的优先级高于第一种方式,第一种方式无法直接为Activity指定FLAG_ACTIVITY_CLEAR_TOP标识,第二种方式无法为Activity指定singleInstance模式。

  Activity常用的Flags:

    一、FLAG_ACTIVITY_NEW_TASK,作用是为Activity指定“singleTask”启动模式;

    二、FLAG_ACTIVITY_SINGLE_TOP,作用是为Activity指定“singleTop”启动模式;

    三、FLAG_ACTIVITY_CLEAR_TOP,当它启动时,同一个任务栈上所有位于它上面的Activity都要出栈;

    四、FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS,作用是具有该标记的Activity不会出现在历史Activity列表中,等同于在XML中指定android:excludeFromRecents = “true”;

2-2IntentFilter的匹配规则

IntentFilter中的过滤信息有action、category、data,为了匹配过滤列表,需要同时匹配过滤列表中的action、category、data信息,否则匹配失败,一个过滤列表的action、category和data可以有多个,一个Activity中可以有多个intent-filter,一个Intent只要能匹配任何一组intent-filter即可成功启动对应的Activity。

(1)action的匹配规则

只要Intent中的action能够和过滤规则中的任何一个action相同即可匹配成功,action区分大小写

(2)category的匹配规则

如果Intent含有category,那么每个category必须要在Activity在XML文件中声明的category中可以找得到;

如果Intent不含有category,并且XML文件中必须声明

也可以成功匹配,因为在使用startActivity或者startActivityForResult时,会自动为该Intent添加一个android.intent.category.DEFAULT这个category,如果未在XML文件中声明

如果不给Intent指定category,会crash掉;

(3)data的匹配规则

data的结构组成:mimeType和URI,mimeType指媒体类型,比如:image/jpeg、audio/mpeg4-generic和video/*等

URI的结构:

<scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]
           

Scheme:URI的模式,比如:http、file、content等,如果URI没有指定Scheme,那么整个URI的其他参数是无效的;

Host:URI的主机名,例如:www.baidu.com,如果host未指定,那么其他参数无效;

Port:URI的端口号;

Path:表示完整路径信息;

PathPattern:也表示完整的路径信息,但是可以包含通配符”*”,*表示0个或多个任意字符;

pathPrefix:表示路径的前缀信息;

data的匹配规则和action规则类似,要求intent必须要含有data数据,并且data数据能够完全匹配过滤规则中的某一个data。