Activity的生命周期、任务栈、启动模式

Activity的生命周期

Activity的生命周期分两种情况,一种是正常情况下的生命周期,一种是由于横竖屏切换导致的异常情况下的生命周期。

一、正常情况下的生命周期

Activity在正常情况下的生命周期有7个,打开时调用三个,关闭时调用三个,在加上一个onRestart,下面分别进行介绍:

  • onCreate:调用该方法时,说明Activity正在被创建,可以做一些页面的初始化操作。
  • onStart:调用该方法时,说明Activity可见并即将开始,但是还没有出现在前台,还没有获取焦点,还不能和用户进行交互。
  • onResume:调用该方法时,说明Activity已经出现在前台了,已经获取到了焦点,能够和用户进行交互了。
  • onPause:调用该方法时,说明Activity失去焦点了(不在前台了)。
  • onStop:调用该方法时,说明Activity不可见并即将停止,和onStart相呼应。
  • onDestory:调用该方法时,说明Activity即将被销毁,可以做一些资源释放、回收的操作。
  • onRestart:调用该方法时,说明Activity正在重新启动,Activity从不可见状态变为了可见状态,比如切到后台或者打开一个新的页面,然后又重新回到这个Activity,就会调用该方法。

以下几点需要注意:
(1)onStart和onResume的对比:两者都说明Activity已经显示出来了,但是onStart的时候Activity还在后台(还没有焦点),onResume的时候Activity才显示在前台(已经有焦点了)。
(2)当打开新的Activity时,当前Activity会调用onPause和onStop,但是如果新Activity使用了透明主题,那么当前Activity就不会回调onStop了。
(3)当打开新的Activity时,会先调用当前Activity的onPause,然后调用新Activity的onCreate、onStart、onResume,然后在调用当前Activity的onStop,所以为了新Activity能尽快显示在前台,不要在onPause中做太多的操作,可以把一些操作放到onStop中去。

二、异常情况下的生命周期

当横竖屏切换时导致Activity被杀死,就会触发Activity生命周期的异常情况,下面对异常情况进行分析:

  • 横竖屏切换导致Activity被销毁并重新创建
    默认情况下,当发生横竖屏切换时,Activity就会被销毁并重新创建。其onPause、onStop、onDestory都会被调用,由于Activity是异常情况下终止的,所以系统会调用onSaveInstanceState方法来保存当前Activity的状态,当Activity被重建后,系统会调用onRestoreInstanceState方法恢复之前在onSaveInstanceState方法中保存的数据。在调用时序上onSaveInstanceState的调用在onStop之前,它和onPause没有一定的时序关系。onRestoreInstanceState的调用在onStart之后。
    系统只在Activity异常终止的情况下才会调用onSaveInstanceState和onRestoreInstance来存储和恢复数据,其他情况下不会触发该过程。

  • 横竖屏切换导致Activity被销毁并重新创建
    给Activity指定configChanges属性值为orientation,这样屏幕旋转时Activity就不会重新创建了。

Activity的任务栈和启动模式

Activtity的任务栈:任务栈中存放着Activity的实例,是后进先出的结构。默认情况下一个应用的所有Activity都是放到一个任务栈里的,并且该任务栈的名字是应用的包名。

Activity的启动模式有四种:standard、singleTop、singleTask、singleInstance,下面分别介绍每种启动模式:

  • standard:标准启动模式,也是系统默认的启动模式。每次启动一个Activity都会创建一个新的实例放到任务栈中。在这种启动模式下,谁启动了这个Activity,那么这个Activity的实例就运行在启动它的那个Activity的任务栈中,比如A启动了B(B是标准模式),那么B就会运行在A所在的任务栈中。
    有这么一种情况,就是当我们用非Activity的Context(比如ApplicatonContext、BrocastReceiver等)去启动standard模式的Activity时,会报异常。这是因为标准模式下,Activity会进入启动它的那个Activiyt的任务栈中,而非Acivity的Context是没有任务栈的,所以就会报错。解决这个问题,就需要给待启动的Activity指定一个标记位FLAG_ACTIVITY_NEW_TASK(相当于让该Activity以singleTask模式启动),这样启动的时候就会为它创建一个新的任务栈。

  • singleTop:栈顶复用模式。在这种启动模式下,如果要启动的Activity已经位于任务栈的顶部了,那么该Activity就不会被重新创建,同时会调用它的onNewIntent方法,可以通过此方法中的Intent获取一些参数信息。如果待启动的Activity不存在或者已经存在但不是位于栈顶,那么就会创建一个新的Activity压入栈顶。

  • singleTask:栈内复用模式。这种模式分3种情形进行讨论,比如要启动一个新的Activity A(singleTask模式)那么会有下面3种情况:
           a、如果A所需要的任务栈不存在,就会创建一个新的相应的任务栈,并把A实例压入栈中。
            b、如果A所需要的任务栈存在,但是该任务栈中没有A实例,那么会把A压入该栈中。
           c、如果A所需要的任务栈存在,并且该任务栈中已经有A了,那么就会把栈中位于A上面的Activity都清除掉,然后把A置于栈顶,同样会调用它的onNewIntent方法。
  • singleInstance:单一实例模式。比如要启动一个该模式的Activity A,那么系统会为Activity A单独创建一个新的任务栈,把A独自放到该任务栈中,如果在次开启A,就不会重新创建A了,而是会复用之前的那个。
    该模式下,虽然系统为A单独创建了一个新的任务栈,但是该任务栈的名字还是应用的包名。如果A在启动一个standard模式的Activity B,那么B会进入系统默认的任务栈中,不会跟A在一个任务栈中。

系统提供的有很多的参数对任务栈和启动模式都有影响,这些参数相组合的情况不能穷尽,没必要都去深究,下面介绍一个比较常见的也比较重要的一个参数TaskAffinity,这个参数标识了一个Activity所需要的任务栈的名字,默认情况下,所有Activity所需要的任务栈的名字为应用的包名。但是我们也可以单独为一个Activity指定任务栈名字,TaskAffinity就可以实现该效果,下面是TaskAffinity对不同的启动模式的影响:

  • singleTask模式下:TaskAffinity的值如果与包名不同,就会开启一个新的任务栈,如果与包名相同就不会新建任务栈。
  • standard和singleTop模式下:单独指定TaskAffinity没有意义,不管TaskAffinity的值是否与包名相同,都不会开启新的任务栈。 但是如果指定TaskAffinity的值与包名不同,并且启动Activity的时候在添加一个FLAG_ACTIVITY_NEW_TASK标志位(相当于将启动模式置为singleTask了)就会新建一个任务栈。
  • singleInstance模式:不受TaskAffinity的影响。

多进程的情况,多进程的Activity也是处于应用默认任务栈里的。比如Activity A启动了另一个进程的Activity B(B是另一个应用的页面,或者跟A一个应用但是单独指定了进程),这个时候B会进入A所在的任务栈中。

Activity启动时常见的标记位

  1. FLAG_ACTIVITY_NEW_TASK:这个标记位将要启动的Activity以singleTask的效果启动。
  2. FLAG_ACTIVITY_SINGLE_TOP:这个标记位将要启动的Activity以singleTop的效果启动。
  3. FLAG_ACTIVITY_CLEAR_TOP:这个标记位会将同一任务栈里,要启动的Activity上面的Activity都清理出栈。 如果被启动的Activity的启动模式是singleTask,那么最终效果就是singleTask模式启动的效果。 如果被启动的Activity的启动模式是standard,如果任务栈中已经有该Activity了,那么该Activity连同它上面的Activity都会出栈(包含自身),在创建一个新的Activity压人栈顶。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值