Android 组件 — Activity (生命周期管理)

Activity生命周期管理


 开发出一款健壮而且灵活的app的关键就是,管理好Activity的生命周期,而管理好Activity生命周期则需要实现合理的回调方法。 Activity的生命周期直接受到与其他Activity的关系、任务及回退栈(back stack)的影响。

一个Activity存在三个基本的状态:

Resumed
Activity 已经在前台运行,你在屏幕上可以看见,而且获得了用户的焦点。(这个状态也可以称作“运行”)
Paused
如果运行Activity A时弹出了Activity B,Activity B并非是全屏,而是覆盖在Activity A之上,这时Activity A会丢失用户焦点,Activity B处于前台且获得用户焦点,则称Activity A处于paused状态。Activity A会在驻留在内存中,它会维护所有的状态及成员信息,而且保持着与窗口管理器的连接。不过Activity A也可能在内存极度不足被系统销毁。
Stopped
如果运行Activity A弹出了一个Activity B,而且被Activity B完全遮盖住,则称Activity A处于stopped状态。这时Activity A仍然是存活在内存中,它会维护所有的状态和成员信息,不过它断开了与窗口管理器的连接。但是Activity A对用户来说是不可见的,所以系统可以在缺乏内存是将其销毁。
如果Activity已经暂停或者关闭,你也可以调用 finish()方法让系统会释放Activity占用内存,或者直接终止Activity所在的进程,当Activity异常终止后重新打开时,必须重新创建Activity。

生命周期回调函数

当一个Activity在不同的状态转换时,系统会调用不同的回调方法通知Activity。所有的回调方法可以被复写,当Activity发生变化的时候你就可以在回调方法内部实现一些处理。在下面的例子中列出了Activity最基本的回调函数: 

public class ExampleActivity extends Activity { 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        // The activity is being created. 
    } 
    @Override 
    protected void onStart() { 
        super.onStart(); 
        // The activity is about to become visible. 
    } 
    @Override 
    protected void onResume() { 
        super.onResume(); 
        // The activity has become visible (it is now "resumed"). 
    } 
    @Override 
    protected void onPause() { 
        super.onPause(); 
        // Another activity is taking focus (this activity is about to be "paused"). 
    } 
    @Override 
    protected void onStop() { 
        super.onStop(); 
        // The activity is no longer visible (it is now "stopped") 
    } 
    @Override 
    protected void onDestroy() { 
        super.onDestroy(); 
        // The activity is about to be destroyed. 
    } 
}

 PS:如同上面的例子,如果复写Activity的回调方法必须调用父类的方法。

总的来说,这些方法涵盖了Activity的整个生命周期。通过实现这些方法,你可以监听Activity 生命周期的三个嵌套循环。

  • 完整周期(entire lifetime)发生在调用onCreate()和onDestroy()之间。在onCreate()中你的Activity需要设置“全局的”状态(比如设置layout),也需要在onDestroy()中释放占用的资源。比如,你的Activity创建了一个运行在后台的线程用来从网络中下载数据,它可能会在onCreate()中创建,在onDestroy()中终止。
  • 可见周期(visible lifetime)发生在调用onStart()和onStop()之间,在这段时间内,用户可以在屏幕上看见Activity的界面也可以进行操作。比如,在调用onStop()的时候就代表Activity不可见,在调用者两个回调方法之间你可以将需要展示给用户的资源通过Activity显示。在Activity的整个周期内,系统可能会因为Activity在可见/不可见之间多次切换,而多次调用onStart()和onStop()方法。
  • 前景周期(foreground lifetime)发生在调用onResume()和onPause()之间,在这段时间,Activity在屏幕上覆盖在其他的Activity之上,而且获得了用户的输入焦点。由于这两个状态之间切换频繁,为了避免用户等待的时间过长,不应该在这两个回调方法中处理耗时的任务。

图1显示了Activity不同状态切换的流程图。矩形框代表了需要实做的回调方法。

 

Figure 1. The activity lifecycle.

 

 

下面的表1详细的列出了Activity回调方法。

表 1. 

MethodDescriptionKillable after?Next
onCreate()Called when the activity is first created.      This is where you should do all of your normal static set up —      create views, bind data to lists, and so on.  This method is passed      a Bundle object containing the activity's previous state, if that      state was captured (see Saving Activity State,      later).     

Always followed by onStart().

NoonStart()
 onRestart()Called after the activity has been stopped, just prior to it being       started again.      

Always followed by onStart()

NoonStart()
onStart()Called just before the activity becomes visible to the user.      

Followed by onResume() if the activity comes       to the foreground, oronStop() if it becomes hidden.

NoonResume()
or
onStop()
 onResume()Called just before the activity starts       interacting with the user.  At this point the activity is at       the top of the activity stack, with user input going to it.      

Always followed by onPause().

NoonPause()
onPause()Called when the system is about to start resuming another       activity.  This method is typically used to commit unsaved changes to       persistent data, stop animations and other things that may be consuming       CPU, and so on.  It should do whatever it does very quickly, because       the next activity will not be resumed until it returns.      

Followed either by onResume() if the activity       returns back to the front, or byonStop() if it becomes       invisible to the user.

YesonResume()
or
onStop()
onStop()Called when the activity is no longer visible to the user.  This       may happen because it is being destroyed, or because another activity       (either an existing one or a new one) has been resumed and is covering it.      

Followed either by onRestart() if       the activity is coming back to interact with the user, or by      onDestroy() if this activity is going away.

YesonRestart()
or
onDestroy()
onDestroy()Called before the activity is destroyed.  This is the final call       that the activity will receive.  It could be called either because the       activity is finishing (someone calledfinish() on it), or because the system is temporarily destroying this       instance of the activity to save space.  You can distinguish       between these two scenarios with theisFinishing() method.Yesnothing

 

 “Killable after ?” 表示是否允许系统在回调方法返回后的任意时间点去销毁Activity所在的进程。其中有三个方法标的是“yes”:(onPause()、onStop()、onDestroy())。从之前的流程图可以看出,在创建Activity之后,想要销毁Activity所在的进程之前,至少会先调用onPause()方法,在内存紧张的情况下,不会调用onStop()和onDestroy()方法。因此,你需要在onPause()中保存一些核心的用户数据(比如用户编辑的内容)。然而,你必须分辨哪些数据需要在onPause()中保存,因为任何耗时的操作都会导致切换到下一个界面的时间太长,从而降低了用户体验。

 标识为“NO”的方法从被调用的那一刻起,它所在的进程将不能被kill。因此,一个Activity可被终结是从onPause()返回的时间点算起,直到调用onResume()时。

PS:不过从技术的角度上讲,Activity可能在任意一个状态下被终结掉,不过只有在系统资源极度匮乏的情况下才有可能,这就会在 Processes and Threading中详细讨论。

保存Activity的状态

 Activity生命周期的管理一章中有提到当一个Activity已经暂停或者停止,Activity的状态会被保存起来。这是事实,因为Activity处于Pause/stop的时候任然驻留在内存中(所有的成员和状态信息都还保留着)。

 然而,当系统因为回收内存去销毁一个Activity时,Activity对象就不存在了,所以系统就不能简单的完全恢复Activity。相反,如果用户返回到该Activity时,系统必须重新创建Activity对象,这个时候用户还不知道Activity已经销毁而且重新被创建,用户仍然希望Activity就是他之前看到的样子。在这种情况下,你就必须实现一个可选的回调函数让程序能够保存Activity非常重要的状态信息:onSaveInstanceState().

系统会在Activity被销毁之前调用 onSaveInstanceState(),并且会传递一个Bundle参数,以键值对的方式保存Activity的状态信息。然后,如果系统销毁了Activity所在的进程后,用户需要返回到Activity的界面,这个时候系统会重新创建Activity并且会将之前保存的Bundle传递给onCreate() 和onRestoreInstanceState()。使用任何一种方法你都可以从Bundle中取出之前的信息重新存储给Activity的状态。如果没有状态信息,则不需要重新存储,Bundle的值将会是null(比如Activity第一次被创建的时候)。

 

 

图2. Activity重新获取到用户焦点的两种方式:如果Activity被销毁,回到该Activity时会重新创建Activity并且重新读取销毁前的状态,如果Activity只是停止了,回到该Activity时直接恢复状态就行了。

提示: 并不是每次销毁Activity都会调用 onSaveInstanceState() ,因为有的情况下是不需要保存Activity状态的(比如用户从当前的Activity 按"back"键 离开时,用户很明确的想要关闭Activity页面)。如果系统需要调用onSaveInstanceState(),那它一定会在onStop()之前调用,但不一定是在onPause().之前调用。

然而,即使你不在Activity中复写onSaveInstanceState()onSaveInstanceState()会在父类中默认实现,用于存储Activity的某些状态。比较特殊的是,这个默认的实现会调用布局中每一个view相应的onSaveInstanceState()方法,这样每一个view就可以提供资深需要保存的信息。绝大多数在Android framework的控件都会实现这个方法,当任何页面可见性发生变化时可以自动的保存和重建。举个例子,EditText 控件会保存编辑的文字,CheckBox控件会保存是否选中。你唯一要做的是给每一个需要保存状态的控件设置ID(android:id),如果控件没有设置ID,则不能保存状态。

 你也可以通过设置 android:saveEnabled 或者setSaveEnabled()来明确的禁止保存控件的状态。通常情况下你是不需要设置这个属性,除非你是想选择性的保存UI 布局中的view。

  尽管Activity父类中会默认实现onSaveInstanceState()来保存UI中必要的信息,但是你仍然有可能需要复写这个可选的回调方法,比如,你可能需要保存成员的值,而这个成员在Activity的生命周期中是变化的,重新创建Activity时需要知道上一次的值。

 因为Activity父类会默认实现onSaveInstanceState()onRestoreInstanceState()方法,你在复写该方法的时候一定要先调用父类中的方法,然后再执行其他操作。

提示:因为onSaveInstanceState()不能确保每次都调用,你应该在这个方法中存储一些暂时性的Activity UI 状态,而不能在该方法中试图去保存一些持久化的数据。那些需要保存到Database的数据应该在onPause()中完成。

 有一个很好的方法可以测试app重新存储Activity的状态,就是旋转Android设备的屏幕。当屏幕的方向发生变化的时候,系统会先销毁Activity,然后根据屏幕的方向重新配置所需的资源,并重新创建Activity。仅仅是这个原因,你就必须保存Activity在重新创建的时候某些UI的状态是正确的,因为用户在使用app的时候,很有可能会旋转屏幕。

处理配置变化

 某些设备的配置在运行的过程中是会发生变化的(比如屏幕的方向、键盘的类型、语言)。当发生这种情况的时候,Android会重新创建正在前台运行的Activity(系统先调用onDestroy(),紧接着再调用onCreate())。这样设计的目的是让你的app能重新加载你预先提供的替代资源来自动适应新的配置(比如不同的屏幕方向和大小加载不同的layout)。

 如果你设计时能处理好屏幕方向变化导致重启Activity以及Activity 状态的重建,你的app就能更灵活的适应Activity 生命周期中的突发事件。

 重启Activity最好的办法是能够通过onSaveInstanceState() andonRestoreInstanceState()重建Activity的状态。

想要了解更过关于运行过程中配置变化以及如何处理这类变化,可以阅读 Handling Runtime Changes.

Activity 之间的协调

 当一个Activity启动另一个时,两个Activity都经历了状态的变化。第一个进入“pause”和“stop”(当然,如果背景可见则不会“stop”),而另外一个Activity则进入“create”。这时他们通过磁盘或者其他方式共享数据,重要的是要明白,当第二个Activity创建的时候,第一个Activity不会完全销毁。而且,启动第二个Activity的过程与关闭第一个Activity的过程会交替重叠到一起。

 生命周期回调方法的执行顺序已经定义好了,特别是在同一个进程中一个Activity启动另一个时。下面是Activity A启动Activity B的执行顺序:

  1. 执行 Activity A 的 onPause() 方法.
  2. 依次执行Activity B的 onCreate(),onStart()onResume() (Activity B 得到用户焦点.)
  3. 然后,如果 Activity A  屏幕上不可见,则执行 onStop().

 这种预先定义好回调时序能有助于你管理状态的变化。举个例子,如果你在停止Activity A 时需要写Database,便于Activity B能从Database中读取到相应的数据,那你必须在onPause()的时候去写Database,而不是在onStop()。

转载请注明出处:http://blog.csdn.net/jack_chen_00/article/details/9980805

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值