在使用Eclipse添加一个新的Activity时,系统会自动生成OnCreate()函数,而其他生命周期函数,例如OnStart() OnReSume()等它是不负责自动生成的,也因为这样,就会被很多开发者忽略,从而产生一些意想不到的错误。
在之前翻译的文章中,分别讲过各个生命周期函数的用法,这里整理一下。
下面是之前翻译的官方文档,里面包含了更详细的实例。
[Andriod官方训练教程]管理Activity的生命活动之开始一个Activity
[Andriod官方训练教程]管理Activity的生命活动之暂停和恢复一个Activity
[Andriod官方训练教程]管理Activity的生命活动之停止和重启一个Activity
[Andriod官方训练教程]管理Activity的生命活动之重新创建一个Activity
一个Activity的生命周期图如下所示:
总体来说,一个Activity只有3种静止状态(其他状态都是瞬时的):
onPause(),然后activity将在Paused状态等候。之后用户再次返回到activity(例如在蓝牙开启对话框出现后,选择了“是”或“否”,该对话框就会自动消失)时,系统将调用onResume()。
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
解决方法是将NavUtils.navigateUpFromSameTask(this)方法改为finish(),即:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
onStop()
和onRestart(),它们允许你明确地控制你的activity该如何停止和重启。和暂停状态(只是局部的UI被阻塞)不同,停止状态确保UI对用户不再可见,而且用户的焦点在单独的一个activity上(或是完全是另一个单独的app)。因为当你的Activity实例停止时系统在内存中仍然保留了它,你可能不需要实现onStop()
和onRestart()(甚至是onStart()方法。对于大多数相对简单的activity,它们可以好好地停止和重启,而你可能只需要使用onPause()来暂停正在进行中的动作并且和系统资源分离
)。当用户离开你的activity时,系统调用onStop()来停止activity (1)。如果当activity停止时用户再次返回,系统调用onRestart(),紧接着调用onStart()
和onResume()
。你应该注意到无论哪种情况下使得activity停止,系统都将先调用onPause()再调用onStop()。
finish()预示着它本身的销毁。当你的activity因为用户按下返回按钮而自己销毁时,系统中的Activity实例会永久消失,因为这样的行为表明activity不再被需要了。
如果你的activity当前是停止状态(请见前面描述何时会进入停止状态)并且在很长时间内没有被使用,或者前台的activity需要更多的资源因此系统需要关闭后台程序来回收内存,系统都有可能会销毁你的activity。这样的因为系统约束(而不是正常的app行为)而销毁activity的情况下,尽管真正的Activity实例已经消失,系统仍然记得它的存在,这样当用户导航回到它时,系统将使用保存的数据(表述了activity销毁时的状态)来创建一个新的activity实例。系统用于重新载入之前状态的保存的数据被叫做“实例状态”,它是一个存储在一个Bundle对象中的键-值对集合。
android:id
属性提供。为了保存额外的有关activity状态的数据,你必须重载onSaveInstanceState()回调方法。当用户准备离开你的activity时系统将调用这个方法,并将它传递给Bundle对象以便你的activity意外销毁时可以被保存。onDestroy()。系统调用该方法作为一个最终信号,你的activity实例将要被完全从系统内存中清除。大多数apps不需要实现这个方法,因为随着你的activity,局部的类引用类型将随之销毁,并且你的activity在 onPause()
and onStop()期间完成了大部分清理工作。但是,如果你的activity包含了后台线程(在onCreate()中创建)或者其他长期执行的资源,如果没有合适地关闭就有可能造成内存泄露,你应该在onDestroy()中结束它们。
除了一种情况外,系统在所有情况下,都是在已经调用了onPause() 和onStop()
后再调用onDestroy()。这种情况是:当你在onCreate()中调用finish()方法。在一些情况下,例如当你的activity运行为一个暂时的决策人来启动另一个activity,你可能在onCreate()中调用finish()来销毁该activity。在这种情况下,系统立刻调用onDestroy(),不再调用其他任何生命周期函数。
当系统销毁你的activity时,它将为你的Activity调用onDestroy()方法。因为你通常应该在onStop()里释放几乎所有的资源,等到你收到一个onDestroy()的调用时,大多数app不需要做太多的事情。这个方法是你清除那些会造成内存泄露的资源的最后的机会,因此你应该确保附加的线程被全部销毁,其他长期运行的动作,像追踪函数等,也同样被停止了。
当系统调用onPause()时,在技术上意味着你的activity仍是部分可见的,而其他情况下这意味着用户正在离开activity,并且将到达Stopped状态。通常情况下,你应该用onPause()回调函数来:
通常,你不应该使用onPause()来将用户变化(例如键入表单的个人信息)永久存储。只有当你确定用户希望这些变化自动存储时(例如草稿邮件),你才应该在onPause()中永久保存这些变化。但是,你应该避免在onPause()中进行密集的CPU工作,例如向数据库写入数据,因为这会减慢向下一个activity的可视转换(相反的,你应该在onStop()中进行这些高负荷的关闭动作)。你应该保持onPause()中完成的操作的数目相对简单,以便当你的activity真的需要停止时,可以允许快速地向用户的下一个目标转换。
当你的activity暂停时,该Activity实例被驻留在内存中,并且在activity继续时被重新调用。你不需要重新初始化那些已经在任何回调函数中创建的部件。
记住,每次你的activity进入前台时,系统都会调用这个方法,包括当第一次创建它时。同样的,你应该实现onResume()来初始化你在onPause()释放的部件,并且执行那些在进入Resumed状态时必须出现的初始化动作(例如开始动画,初始化那些当activity获得用户聚焦时需要的部件)。
onDestroy()回调函数,因为使用onStop()来释放那些可能造成内存泄露的资源是很重要的。尽管onPause()方法在onStop()之前被调用,你应该使用onStop()来进行更大量的、更密集的CPU操作,例如向数据库写入信息。
当你的activity停止时,Activity对象被保留在内存中,然后在activity重新开始时被再次调用。你不需要再次初始化那些在任何回调函数中创建的部件。系统还将跟踪布局中每个View的当前状态,因此如果用户在EditText窗口中输入文字,那这些内容会被保留因此你不需要保存和重新载入它们。
注意:即使在你的activity停止时系统销毁了它,系统仍然在一个Bundle
(一个键-值对的二进制大对象,也就是前面在OnCreate()函数中的参数savedInstanceState)中保留了View对象的状态(例如一个EditText中的文本
),如果用户导航到同样的activity实例系统将重新载入它们。
onRestart()的调用。系统还会调用onStart()方法,这个方法在你的activity变得可见时都会发生(不管是被重启还是第一次被创建)。但是,onRestart()方法仅在activity从停止状态重新开始时才会被调用,因此你需要使用它来执行特殊的恢复工作(仅在activity之前停止了但未被销毁的情况下的必要的工作)。
一个app需要使用onRestart()来重新载入activity的状态是不常见的,因此对于这个应用于母体app的方法没有任何指导。但是,因为你的onStop()方法本质上应该清除你的activity的所有资源,在activity重启时你将需要重新实例化它们。然而,在你的activity第一次创建(这时没有任何存在的activity实例)时,你还需要实例化它们。出于这个原因,你通常应该使用onStart()回调函数作为onStop()方法的对应版本,因为系统在创建你的activity和停止时重启activity都会调用onStart()。
例如,因为用户在返回时可能已经离开你的app很长一段时间了,onStart()方法是一个核实系统性能是可用的的一个绝佳的地方:
最后,讲一下与活动状态的保存与重载有关的两个函数:onSaveInstanceState()和onRestoreInstanceState()。
当系统开始停止你的activity时,它调用onSaveInstanceState() ,因此万一Activity实例必须被重建时你可以指明你想抱保存的额外状态。如果activity被销毁并且一个相同的实例必须被重建,系统将(1)中定义的状态传递给onCreate() 方法 (2) 以及onRestoreInstanceState()方法 (3)。有一些情况下你的activity因为正常的app行为而被销毁,例如当用户按下返回按钮或者你的activity调用了finish()预示着它本身的销毁。当你的activity因为用户按下返回按钮而自己销毁时,系统中的Activity实例会永久消失,因为这样的行为表明activity不再被需要了。
onRestoreInstanceState()回调函数都接收包含了相同的状态信息的Bundle对象。因为onCreate()方法在创建一个新的实例以及重建一个先前的实例都会被调用,在你试图读一个Bundle之前你必须检查它的状态是否是null。如果它是null,那么系统将会创建一个新的activity实例,而不是重新载入之前被销毁的一个。你可以在onCreate()中重载相同的状态数据。
你也可能选择去实现onRestoreInstanceState()(系统在onStart()方法后调用)而不是在onCreate()重新载入状态。系统仅在有某个保存的状态需要被重载时才调用onRestoreInstanceState()。
警告:永远先调用onRestoreInstanceState()的父类实现,因为默认实现可以重新载入view层级结构的状态。