全面解析Activity(一): Activity的生命周期

Activity是整个Android app直接与用户交互的核心组件。作为四大组件中出现频率最高的组件,我们在Android的各个地方都能看到它的影子。Activity中文直接翻译为"活动",其实翻译成"界面"更好理解。正常情况下,除了Window、Dialog和Toast,我们能看到的界面的确只有Activity。

深入了解Activity的工作模式、生命周期与管理模式,是了解Android系统的基础,也是开发过程中必备的基本技能。

一.生命周期

谷歌给了我们一张图来表示Activity的生命周期,他希望Activity能被开发者所控制,而不是一匹脱缰的野马。下图是最经典的,也是我们最常见的:

全面解析Activity(一): Activity的生命周期_第1张图片

(一)生命周期中各个方法的含义和作用

(1)onCreate():create表示创建,这是Activity生命周期的第一个方法,也是我们在android开发中接触的最多的生命周期方法.它本身的作用是进行Activity的一些初始化工作,比如使用setContentView加载布局,对一些控件和变量进行初始化等.但也有很多人将很多与初始化无关的代码放在这,其实这是不规范的.此时Activity还在后台。不可见,所以动画不应该在这里初始化,因为看不到……

(2)onStart():start表示启动,这是Activity生命周期的第二个方法.此时Activity已经可见了,但是还没出现在前台,我们还看不到,无法与Activity交互。其实将Activity的初始化工作放在这也没有什么问题,放在onCreate中是由于官方推荐的以及我们开发的习惯。

(3)onResume():resume表示继续、重新开始,这名字和它的职责也相同。此时Activity经过前两个阶段的初始化已经蓄势待发。Activity在这个阶段已经出现在前台并且可见了。这个阶段可以打开独占设备。

(4)onPause():pause表示暂停,当Activity要跳到另一个Activity或应用正常退出时都会执行这个方法。此时Activity在前台并可见,我们可以进行一些轻量级的存储数据和去初始化的工作,不能太耗时,因为在跳转Activity时只有当一个Activity执行完了onPause方法后另一个Activity才会启动,而且android中指定如果onPause在500ms即0.5秒内没有执行完毕的话就会强制关闭Activity。从生命周期图中发现可以在这快速重启,但这种情况其实很罕见,比如用户切到下一个Activity的途中按back键快速得切回来。

(5)onStop():stop表示停止,此时Activity已经不可见了,但是Activity对象还在内存中,没有被销毁。这个阶段的主要工作也是做一些资源的回收工作。

(6)onDestroy():destroy表示毁灭,这个阶段Activity被销毁,不可见,我们可以将还没释放的资源释放,以及进行一些回收工作。

(7)onRestart():restart表示重新开始,Activity在这时可见,当用户按Home键切换到桌面后又切回来或者从后一个Activity切回前一个Activity就会触发这个方法。这里一般不做什么操作。

(二)联系与区别

(1)onCreate()和onStart()之间有什么区别?
①可见与不可见的区别。前者不可见,后者可见。
②执行次数的区别。onCreate方法只在Activity创建时执行一次,而onStart方法在Activity的切换以及按Home键返回桌面再切回应用的过程中被多次调用。因此Bundle数据的恢复在onStart中进行比onCreate中执行更合适。
③onCreate能做的事onStart其实都能做,但是onstart能做的事onCreate却未必适合做。如前文所说的,setContentView和资源初始化在两者都能做,然而想动画的初始化在onStart中做比较好。

(2)onStart()方法和onResume()方法有什么区别?
①是否在前台。onStart方法中Activity可见但不在前台,不可交互,而在onResume中在前台。
②职责不同,onStart方法中主要还是进行初始化工作,而onResume方法,根据官方的建议,可以做开启动画和独占设备的操作。

(3)onPause()方法和onStop()方法有什么区别?
①是否可见。onPause时Activity可见,onStop时Activity不可见,但Activity对象还在内存中。
②在系统内存不足的时候可能不会执行onStop方法,因此程序状态的保存、独占设备和动画的关闭、以及一些数据的保存最好在onPause中进行,但要注意不能太耗时。

(4)onStop()方法和onDestroy()方法有什么区别?
onStop阶段Activity还没有被销毁,对象还在内存中,此时可以通过切换Activity再次回到该Activity,而onDestroy阶段Acivity被销毁。

二.Activity的状态分析

开发者当然不必实现所有的生命周期方法,但知道每一个生命周期状态的含义,可以让我们更好地掌握Activity,让它能更好地完成你所期望的效果。

上面的生命周期图列举了Activity的生命周期状态,但其中只有三个状态是稳定的,而其他状态都只是过渡状态,很快就会消失。

  • Resumed
    这个状态,也就是前面所说的Activity/Running形态,此时候,Activity处于Activity栈的最顶层,处理用户的交互。

  • Paused
    Activity失去焦点,被一个新的非全屏的Activity或者一个透明的Activity放置在栈顶时,Activity就转换成了paused形态,他失去了与用户交互的能力,所有状态信息、成员变量都还保留着,只有在系统内存极低的情况下,才会被系统回收。

  • Stopped
    如果一个Activity被另一个Activity完全覆盖,那么Activity就会进入stop形态,此时他不在可见,但依然保留着所有的状态和成员变量。

(一)Activity的启动与销毁过程

在系统调用onCreate()方法之后,就会马上调用onStart(),然后继续调用onResume()来进图运行状态,最后都会停在onResume()状态,完成启动,系统会调用onDestroy()来结束一个Activity的生命周期让他毁掉kill状态。

以上就是一个Activity的启动和销毁的过程。

  • onCreate()中:创建基本的UI元素
  • onPause()和onStop():清除Acvtivity的资源,避免浪费。
  • onDestroy():因为引用会在Activity销毁的时候销毁,而线程不会,所以清除开启的线程。

(二)Activity的暂停与恢复过程

当栈顶的Activity部分不可见的时候,就会导致Activity进入onPause()方法,当结束阻塞后,就会调用onResume()方法来回复到Resume形态。

  • onPause():释放系统,如Camera、sensor(传感器)、receivers。
  • onResume():需要重新初始化onPause()释放的资源。

(三)Activity的停止过程

栈顶的Activity部分不可见的时候,实际上后续会有两种可能,从部分不可见到可见,也就是恢复过程,从部分不可见到完全不可见,也就是停止过程,系统在当前Activity不可见的时候调用onPause()方法。

(四)Activity的重新创建过程

这部分是最复杂的,我将在第四部分进行说明。

三.设备旋转与生命周期

对于这个问题的讨论,我们通过输出日志的方式进行(如果是真机的话,记得将手机设置成自动旋转,模拟器的话点击工具栏的旋转按钮)。

全面解析Activity(一): Activity的生命周期_第2张图片

从日志可以清晰看出:设备旋转后,系统会销毁当前Activity实例,然后创建一个新的Activity实例.再次旋转设备,又一次见证这个销毁与再创建的过程。

因此,我们在开发过程中,如没有特殊需求,为了避免用户因旋转设备导致Activity生命周期改变,而出现意想不到的问题,我们会进行设置设置.方法如下:

方法一:在AndroidManifest.xml中设置
android:screenOrientation="portrait"(始终保持竖屏的生命周期)
android:screenOrientation="landscape"(始终保持横屏的生命周期)



***********************************

方法二:在代码中设置
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); (始终保持竖屏的生命周期)
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);(始终保持横屏的生命周期)

@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
   setContentView(R.layout.activity_lifecy);
}

四.再探生命周期

(一)重写onSaveInstanceState(Bundle)方法

在Activity中,onSaveInstanceState()是开发人员进阶必知的方法,其中一个参数的onSaveInstanceState(Bundle outState)来自AppCompatActivity,两个参数的onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState)来自Activity.前者是我们使用最多的。本文的讨论,若无特殊说明,均指一个参数这个方法。

该方法通常在onStop()方法之前由系统调用,除非用户按后退键。(记住,按后退键就是告诉Android,Activity用完了.随后,该Activity就完全从内存中被抹掉,自然,也就没有必要为重建保存数据了。)

方法onSaveInstanceState(Bundle)的默认实现要求所有Activity视图将自身状态数据保存在Bundle对象中。Bundle是存储字符串键与限定类型值之间映射关系(键-值对)的一种结构。

可通过重写onSaveInstanceState(Bundle)方法,将一些数据保存在bundle中,然后在onCreate(Bundle)方法中取回这些数据。代码片段如下:

@Override
protected void onSaveInstanceState(Bundle outState) {
   super.onSaveInstanceState(outState);
   outState.putInt(KEY_INDEX,1);              //存值
}

 @Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_lifecy);
   if (savedInstanceState!=null){
     int anInt = savedInstanceState.getInt(KEY_INDEX,0);
   }
}

注意:在Bundle中储存和恢复的数据类型只有是基本数据类型,以及可以实现Serializable或Parcelable接口的对象。在Bundle中保存定制类对象不是个好办法,因为你取回的对象可能已经没用了。比较好的做法是,通过其他方式保存定制类对象,而在Bundle中保存标识对象的基本类型数据。

从刚刚的代码片段大家可以发现,其用法其实和sharepreference差不多,的确是这样。

(二)数据的保存

用户离开当前Activity界面,或Android需要回收内存时,Activity也会被销毁(例如:用户按了Home键,然后去玩王者荣耀)。基于用户体验考虑,Android从不会为了回收内存而去销毁可见的Activity。只有在调用过onStop()并执行完成后,Activity才会被标为可销毁。

的确,系统随时会销毁已停止的Activity,但我们其实不用担心数据丢失。因为Activity停止时,会调用onSaveInstanceState(Bundle)方法的。那么,保存在onSaveInstanceState(Bundle)的数据该如何幸免于难呢?调用该方法时,用户数据随即被保存在Bundle对象中,然后操作系统将Bundle对象放入Activity记录中。为了便于大家理解,我们增加一个暂存状态到Activity生命周期中,如下图:
全面解析Activity(一): Activity的生命周期_第3张图片

Activity暂存后,其对象不再存在,但操作系统会将Activity记录对象保存起来。这样,在需要恢复Activity时,操作系统可以使用暂存的Activity记录重新激活Activity。

注意:Activity进入暂存状态并不一定需要调用onDestory()方法。不过,onStop()和onSaveInstanceState(Bundle)方法是两个可靠的方法(除非设备出现重大故障)。因而,常见的做法就是,重写onSaveInstanceState(Bundle)方法,在Bundle对象中,保存当前Activity的小的或者暂存状态的数据;重写onStop方法,保存永久性数据,如用户编辑的文字等。onStop()方法调用完,Activity随时会被系统销毁,所以用它保存永久性数据。

那么,暂存的Activity记录到底能够保存多久呢?前面说了,用户按了后退键后,系统会彻底销毁当前的Activity。此时,暂存的Activity记录同时被清除。此外,系统重启的话,暂存的Activity记录也会被清除。


源码下载

点我下载


参考

  1. 官方开发者文档: 点我跳转
  2. 《Android编程权威指南(第3版)》
  3. 《Android群英传》
  4. 《Android开发艺术探究》

关于我

  1. 一个热爱Android,也喜欢交友的菜鸟. QQ:984992087
  2. github链接: 点我跳转

你可能感兴趣的:(Android组件框架,application)