Activity的生命周期

原创
2015/11/07 15:40
阅读数 75

###开始活动

在Activity的生命周期中,系统会调用一系列核心的生命周期方法,每一个生命周期方法类似于金字塔的一层,整个生命周期可以看成是一个阶梯金字塔结构。当系统创建一个Activity实例时,生命周期状态向着顶端状态移动,每次移动都会调用相应的回调方法。

当用户离开Activity时,生命周期就会从顶端状态往下移动,同样的,每次移动都会有相应的回调方法。系统通过这种方式一步一步的“拆除”Activity。在某些时候,Activity会移动到某种状态并维持等待,之后又返回到顶端状态,恢复用户离开时候的样子。(例如当用户界面切换到别的应用或另一个Activity时,当前Activity的生命周期状态下移至Stopped,切换回来时,状态返回至Resumed)

根据应用程序的复杂性,我们大可不必实现所有的回调方法,但是理解每个回调方法扮演的角色以及如何实现它们确保提升用户体验是至关重要的。实现回调方法时,确保你的应用能够做到一下几点:

  1. 当用户使用你的应用时,接到一个电话或者跳到别的应用不至于崩溃
  2. 当用户不是经常使用时不要消耗系统资源
  3. 如果用户离开应用并稍后返回,不会丢失用户的进度
  4. 在用户在横屏和竖屏之间切换时不要导致应用崩溃

事实上,Activity只会在以下三个状态之一中停留:

**Resumed:**在这种状态下,Activity在前台与用户交互

**Paused:**在这种状态下,Activity被另一个Activity部分遮盖,另一个Activity在前台处于半透明或者还没有完全覆盖全屏的状态,这个时候的Activity不能接收用户的输入也不执行任何代码。

**Stopped:**在这种状态下,Activity完全隐藏在后台,不显示给用户,同时,Activity实例的状态信息例如成员变量被保留下来。这种状态下也不执行任何代码。

.

Note: 另外两个状态Created和Started是非常短暂的状态,系统会快速从这些状态通过调用回调方法进入下一个状态,也就是说系统调用onCreate()方法之后就会立刻调用onStart()方法,然后立刻调用onResume()方法。

.

系统在创建每一个Activity实例时都是通过调用它的onCreate()方法,并且在整个生命周期只会调用一次,所以你必须要实现onCreate()方法去执行基本的应用启动逻辑,例如定义用户接口,实例化变量...

一旦onCreate()执行完成,系统就会快速的执行onStart()onResume()方法。Activity永远不会在Created和Started这两个状态下停留。从技术的角度上讲,Activity开始变得可见是在onStart()调用之后,但是onResume()紧接着被迅速的调用,Activity就一直维持在Resumed状态之下直到别的什么动作改变它。

onDestroy()方法是Activity存在的最后的信号,这意味着Activity随后将被从系统内存中移除。大多数时候app没必要实现这个方法,因为Activity类中的变量引用会随着Activity一起被销毁,Activity尽量在onPause()onStop()调用期间被清理干净,然而如果Activity包含了一些后台进程,那么你就必须在onDestroy()的时候将它杀死,释放内存。

Note: 一般情况下,系统在调用onPause()onStop()之后才会调用onDestroy(),但是除了一种情况:当你在onCreate()方法内临时决定finish()这个Activity去启动例外一个时,系统会立刻调用onDestroy()方法不在经过其他生命周期。

.

###暂停和继续

在使用应用的过程中,前台Activity有时会被其他导致Activity暂停的可视组件阻挡。 例如,当半透明Activity打开时(比如对话框样式中的Activity,但是普通对话框并不能让Activity暂停,当当前Activity弹出一个对话框时,焦点还是在当前Activity中),上一个Activity会暂停。 只要Activity仍然部分可见但目前又未处于焦点之中,它会一直暂停。但是,一旦Activity完全被阻挡并且不可见,它便停止。

当Activity进入暂停状态时,系统就会调用onPause()方法,从技术上来讲这时的Activity仍然处于部分可见的状态,但是失去了焦点,往往意味着它很快要进入“停止”状态,通常在onPause()回调中我们需要做一下工作:

  1. 停止动画、轮番或者其他可能消耗CPU的操作
  2. 提交未保存的更改
  3. 释放系统资源,比如广播接收器、照相机、暂停视频,总之不要在没有必要的时候消耗资源,浪费电。

onPause()onStart()一样在两个界面切换间调用,所以你可以在这个onPause()回调内做存储用户信息之类的简单操作,但是避免期间内执行CPU密集型这样耗时的工作,比如向数据库写入信息,因为这样会拖慢向下一个Activity过渡的过程,造成影响用户体验的卡顿现象。

系统通过onResume()回调从现让Activity从“暂停”状态回到活动状态。注意,Resumed有两个“入度”,一个是从started状态进入的,另一个就是从Paused状态,onResum()回调有时候要小心对入口区分对待。

. ###停止和继续

不同于“暂停”状态,“停止”状态保证UI不可见,并且用户焦点在另外的Activity中。正确停止和重新开始Activity是Activity生命周期中的重要过程,其可确保您的用户知晓应用始终保持Activity状态并且不会丢失进度。有几种Activity停止和重新开始的关键场景:

  • 用户打开“最近应用”窗口并从您的应用切换到另一个应用。当前位于前台的您的应用中的Activity将停止。 如果用户从主屏幕启动器图标或“最近应用”窗口返回到您的应用,Activity会重新开始。
  • 用户在您的应用中执行开始新Activity的操作。当第二个Activity创建好后,当前Activity便停止。 如果用户之后按了返回按钮,第一个Activity会重新开始。
  • 用户在其手机上使用您的应用的同时接听来电。

Activity提供两种生命周期方法onStop()onRestart()专门处理正在停止和重新开始的操作,对于大多数简单的Activity而言,我们并不需要实现它们,系统停止Activity时会将它暂时保留在内存中,系统还会在布局中跟踪每个 View 的当前状态,如果用户在 EditText 小工具中输入文本,该内容会保留,因此您无需保存即可恢复它。我们更多时候使用onPause()来暂停某些动作,节省资源。

我们尽量在Activity进入Stopped状态前释放几乎所有用户不使用时不需要的资源,一旦你的Activity处于停止状态,系统在迫切需要内存时,可能会销毁该实例,在极端情况下甚至会不调用onDestroy()回调就终止应用进程,因此使用onStop()释放可能“树大遭风”的内存资源是非常重要的。不同于onPause()onStop()更适合执行更大、耗时的关闭操作,比如向数据库写入数据。

**Note:**即使系统在Activity停止状态时强制回收的内存,它仍然会将一些状态数据用Bundle(键值对的二进制大对象)保存下载,以便用户在导航回Activity时能够恢复原来状态。

当Activity从“停止”状态返回前台时,它会调用onRestart()方法,并且它只会在这种情况下被调用,因此,你可以使用它执行只有在Activity停止但未销毁又返回前台的情况下必须执行的特殊恢复工作,例如重新播放视频。

. ###重新创建

activity被销毁一般出于一下几点:

  1. 用户按返回按钮
  2. 通过调用finish()示意自毁
  3. 如果Activity当前被停止或长期未使用,或者前台Activity需要更多资源以致系统必须关闭后台进程恢复内存,系统也可能会销毁Activity。

**Note:**前两者的Activity被销毁是实例概念的销毁,因为行为指示不在需要这个Activity。但是,如果系统因系统局限性(而非正常应用行为)而销毁Activity,尽管 Activity 实际实例已不在,系统会记住其存在,这样,如果用户导航回实例,系统会使用描述Activity被销毁时状态的一组数据重新创建Activity的新实例。 系统用于恢复先前状态的已保存数据被称为“实例状态”,是 Bundle 对象中存储的键值对集合。

.

**Note:**每次用户旋转屏幕时,Activity将被销毁并重新创建。 当屏幕方向变化时,系统会销毁并重新创建前台Activity,因为屏幕配置已更改并且您的Activity可能需要加载备用资源(比如布局)。默认情况下,系统会使用 Bundle 实例状态保存您的Activity布局(比如,输入到 EditText 对象中的文本值)中有关每个 View 对象的信息。 这样,如果您的Activity实例被销毁并重新创建,布局状态便恢复为其先前的状态,且您无需代码。 但是,您的Activity可能具有您要恢复的更多状态信息,比如跟踪用户在Activity中进度的成员变量。

.

要保存Activity额外的状态数据,你需要覆写onSaveInstanceState()回调方法。当用户要离开Activity并在Activity意外销毁时向其传递将保存的 Bundle 对象时,系统会调用此方法。 如果系统必须稍后重新创建Activity实例,它会将相同的 Bundle 对象同时传递给 onRestoreInstanceState()onCreate() 方法。

你可以选择在onCreate()中恢复读取恢复之前的状态,但在此之前你需要判空,如果Bundle为null,说明系统将要创建一个新实例,而不是回复销毁的实例。不过Android更推荐系统在 onStart()方法之后调用的 onRestoreInstanceState()方法 , 系统只有在存在要恢复的已保存状态时才会调用 onRestoreInstanceState() ,因此您无需检查 Bundle 是否为 null:

展开阅读全文
打赏
0
3 收藏
分享
加载中
更多评论
打赏
0 评论
3 收藏
0
分享
返回顶部
顶部