Activity 的生命周期(读书笔记)

Activity 有两种生命周期:典型情况下的生命周期异常情况下的生命周期。典型情况下的生命周期是指在有用户参与的情况下,Activity 所经过的生命周期的改变。异常情况下的生命周期是指 Activity 被系统回收或者由于当前设备的 Configuration 发生改变从而导致被销毁重建

典型情况下的生命周期分析

  • onCreate()
    表示Activity正在被创建,这是生命周期的第一个方法。在这个方法中,我们可以做一些初始化工作,比如调用setContentView去加载界面布局资源、初始化Activity所需数据等
  • onRestart()
    表示Activity正在重新启动。一般情况下,当当前Activity从不可见变为可见状态时,onRestart()就会被调用。这种情形一般是用户行为所导致的,比如用户按Home建切换到桌面或者用户打开了一个新的Activity,这时当前Activity就会暂停,也就是onPause()和onStop()被执行了,接着用户又回到了这个Activity,也就会出现这种情况
  • onStart()
    表示Activity正在被启动,即将开始,这个时候其实可以理解为Activity已经显示出来了,但是我们还看不到,无法进行交互
  • onResume()
    表示Activity已经可见了,并且出现在前台并未开始活动。onStart()的时候Activity还在后台不可见,onResume()的时候已经在前台了用户可见
  • onPause()
    表示Activity正在停止,正常情况下,紧接着onStop()就会被调用。在特殊情况下,如果这个时候快速地再回到当前Activity,那么onResume()就会被调用。在系统急需内存的情况下,处于onPause()的Activity可能会被直接回收而不经过onStop()和onDestory()方法,因此此方法通常用于确认对持久性数据的未保存更改、停止动画以及其他可能消耗 CPU 的内容等,在onPause()中所执行的任务应该是耗时比较短的,因为onPause()必须先执行完,新的Activity的onResume()才会执行,如果此时执行的任务比较耗时将会有影响到下一个Activity的开启,造成很不好的用户体验
  • onStop()
    表示Activity即将终止,可以做一些稍微轻量级的回收工作,不能太耗时
  • onDestroy()
    表示Activity即将被销毁,这是Activity生命周期中的最后一个回调,在这里我们可以做一些回收工作和最终的资源释放
  • 生命周期图如下:(Google Api Guide上的)

典型情况下的生命周期–补充

  1. 当用户打开新的Activity或者切换到桌面的时候,回调过程为:onPause()–>onStop()。这里有一种特殊情况,如果新Activity采用了透明主题,那么当前Activity不会回调onStop()
    当我们在MainActivity打开设置为透明的TransparencyActivity时的启动过程如图所示可证上述结论:
    当我们按返回键回到MainActivity时触发的是MainActivity的onResume()而不是onRestart(),因为打开Transparency的时候并没有触发MainActivity的onStop(),此过程在生命周期图种也有展示

    当启动正常Activity时,如图所示:

  2. 当用户按back建返回时默认的情况为:onPause()–>onStop()–>onDestroy()
    从TempActivity通过按back键后退回MainActivity:

  3. 当按在TransparencyActivity按home键返回桌面,在进入应用时我们会发现很奇特的现象,绿框内为启动Transparency的过程,红框内为按home键返回桌面的过程,蓝框内为重新进入应用的过程

    在重新进入应用时我们发现两个MainActivity和TransparencyActivity都重新加载了,因为TransparencyActivity是被定义为透明的(设置Activity的主题的**true**时,定义Activity为“透明的”但此时,Activity是否为透明还得看具体的设置,但它已经被系统认定为是透明的了),而MainActivity在这种情况下下是属于用户可见的,因此当打开TransparencyActivity时才没有执行onStop(),执行onStop()后Activity就属于用户不可见,即看不到Activity中的内容了
    下图为在MainActivity中打开正常的TempActivity然后按home键回到桌面再重新进入应用的过程

  4. onStart()、onResume()、onPause()、onStop()从描述上差不多,对我们来说的实质不同是什么?
    onStart()和onPause()是从Actiivty是否可见这个角度来回调的,而onResume()和onStop()是从Activity是否处于前台这个角度来回调的,除此之外,在实际使用中没有其他明显区别

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

  • 资源相关的系统配置发生改变导致Activity被杀死并重新创建
    1. 常见的如:屏幕方向发生改变,且应用有设置横竖屏模式
    2. 当系统配置发生改变后,Activity会被销毁,onPause()、onStop()、onDestroy(0均会被调用,同时由于系统是在异常情况下终止的,系统会调用onSaveInstanceState()来保存当前Activity的状态。这个方法的调用时机是在onStop()之前,它和onPause()没有既定的时序关系,它既可能在onPause()之前调用,也可能在onPause()之后调用。需要强调的一点是,这个方法只会出现在Activity被异常从终止的情况下,正常情况下系统不会回调这个方法。当Activity被重新创建后,系统会调用onRestoreInstanceState,并且把Activity销毁时onSaveInstanceState方法所保存的Bundle对象作为参数同时传给onRestoreInstanceState和onCreate()来判断Activity是否被重建,如果被重建了,那么我们就可以取出之前保存的数据并恢复,从时序上来说,onRestoreInstanceState()的调用时机在onStart()之后
    3. 保存和恢复View的层次结构,系统的工作流程:首先Activity被意外终止时,Activity会调用onSaveInstanceState去保存数据,然后Acticity会委托Windows去保存数据,接着Windows在委托它上面的顶级容器去保存数据。最后顶级容器再去一一通知它的子元素来保存数据,这样整个数据保存过程就完成来了。可以发现,这是一种典型的委托思想,上层委托下层、父容器委托子元素去处理一件事情,这种思想在Androud中有很多应用,比如View的绘制过程、事件分发等都是采用类似的思想。
    4. 我们在MainActivity中进行转屏可见如下运行过程,系统只在Activity异常终止的时候才会调用onSaveInstanceState与onRestoreInstanceState来储存和恢复数据,其他情况不会触发这个过程。但是按Home键或者启动新Activity仍然会单独触发onSaveInstanceState的调用
  • 资源内存不足导致优先级的Activity被杀死
    当系统内存不足时,系统就会按照以下优先级去杀死目标Activity所在的进程,并在后续通过onSaveInstanceState和onRestoreInstanceState来存储和恢复数据。如果一个进程中没有四大组件在运行,那么这个进程将很快被系统杀死,因此,一些后台工作不适合脱离四大组件而独立的运行在后台中,这样进程很容易就被杀死。比较好的方法是将后台工作放入Servie中从而保证进程有一定的优先级这样就不容易轻易的被系统杀死
    1. 前台Activity—–正在和用户交互的Activity,优先级别最高
    2. 可见但非前台Activity—–比如Activity中弹出了一个对话框,导致Activity可见但是位于后台无法和前台用户直接交互
    3. 后台Activity—–已经被暂停的Activity,比如执行了onStop(),优先级别低
  • 解决系统配置发生改变后Activity会被重新创建的问题
    要声明由 Activity 处理配置变更,请在清单文件中编辑相应的 元素,以包含 android:configChanges 属性以及代表要处理的配置的值。android:configChanges 属性的文档中列出了该属性的可能值(最常用的值包括 “orientation” 和 “keyboardHidden”,分别用于避免因屏幕方向和可用键盘改变而导致重启)。您可以在该属性中声明多个配置值,方法是 ”|“ 字符分隔这些配置值
    例如,以下清单文件代码声明的 Activity 可同时处理屏幕方向变更和键盘可用性变更:
    1
    2
    3
    <activity android:name=".MyActivity"
    android:configChanges="orientation|keyboardHidden"
    android:label="@string/app_name">
    更多的configChanges项目和含义请看下表:

评论

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×