十八、处理活动生命周期事件
众所周知,Android 设备基本上都是手机。因此,有些活动比其他活动更重要——对用户来说,接电话可能比玩数独更重要。而且,因为它是一部手机,它的内存可能比你现在的台式机或笔记本要少。
由于手机内存有限,你的活动可能会被终止,因为其他活动正在进行,系统需要你的活动的内存。可以把它想象成生命循环的机器人版——你的活动结束了,其他人可能会活下来,以此类推。在您认为活动已经完成之前,甚至在用户认为活动已经完成之前,您都不能假设活动将会运行。这是一个例子,也许是最重要的例子,说明了活动的生命周期将如何影响您自己的应用逻辑。
本章涵盖了构成活动生命周期的各种状态和回调,以及如何恰当地挂钩它们。
薛定谔的活动
一般来说,活动在任何时间点都处于四种状态之一:
- 活动:活动由用户启动,正在运行,在前台。这是你习惯于考虑的活动运作方式。
- 暂停:活动由用户启动,正在运行,并且是可见的,但是通知或其他东西覆盖了屏幕的一部分。在此期间,用户可以看到您的活动,但可能无法与之互动。示例包括提示用户接受来电,或者警告用户电池电量低或电量极低。
- 停止:该活动由用户启动,正在运行,但被其他已经启动或切换到的活动隐藏。您的应用不能直接向用户呈现任何有意义的内容,但是可以通过通知的方式进行通信。
- Dead :要么该活动从未开始(例如,在电话复位之后),要么该活动被终止,可能是由于缺少可用存储器。
生命、死亡和你的活动
Android 使用本节描述的方法调用您的活动,因为活动在上一节列出的四种状态之间转换。一些转换可能会导致多次调用您的活动,有时 Android 会在不调用应用的情况下将其杀死。这整个领域是相当模糊的,可能会发生变化,所以在决定哪些事件值得关注,哪些可以安全忽略时,请密切关注 Android 官方文档以及本节。
请注意,对于所有这些方法,您应该向上链接并调用该方法的超类版本,否则 Android 可能会引发异常。
onCreate()和 onDestroy()
在所有的例子中,我们已经在所有的Activity
子类中实现了onCreate()
。在三种情况下会调用此方法:
- 当活动第一次启动时(例如,从系统重启开始),将使用
null
参数调用onCreate()
。 - 如果活动一直在运行,然后过一段时间被终止,
onCreate()
将被调用,来自onSaveInstanceState()
的Bundle
作为参数(如下一节所述)。 - 如果 activity 一直在运行,并且您已经将 activity 设置为基于不同的设备状态(例如,横向与纵向)拥有不同的资源,那么您的 activity 将被重新创建,并调用
onCreate()
。第 23 章中介绍了如何使用资源。
这里是您初始化 UI 和设置任何需要一次性完成的事情的地方,不管活动是如何使用的。
在生命周期的另一端,当活动关闭时,可能会调用onDestroy()
,这可能是因为名为finish()
的活动(它“结束”了该活动),也可能是因为 Android 需要 RAM 并且过早地关闭了该活动。请注意,如果对 RAM 的需求很紧急(例如,一个来电),可能不会调用onDestroy()
,但是活动仍然会被关闭。因此,onDestroy()
主要是为了干净地释放你在onCreate()
获得的资源(如果有的话)。
在处理包含视图的活动时要小心,该视图由来自数据库(如 SQLite)的适配器填充。谨慎的做法是在数据库和/或适配器对象上调用close()
,但是也要记住,如果您的关闭是突然的,那么您不能依赖在onDestroy()
中调用这些对象。我们将在第 32 章中进一步讨论这个问题。
onStart()、onRestart()和 onStop()
一个活动可以出现在前台,因为它是第一次被启动,或者因为它在被隐藏(例如,被另一个活动或被一个呼入电话)之后被带回到前台。在这两种情况下都会调用onStart()
方法。
在活动已经停止并且现在重新开始的情况下,调用onRestart()
方法。
相反,当活动将要停止时,调用onStop()
。
onPause()和 onResume()
在您的活动进入前台之前调用onResume()
方法,无论是在最初启动之后、从停止状态重新启动之后,还是在弹出对话框(例如,来电)被清除之后。这是一个很好的地方,可以根据用户上次查看您的活动后发生的事情来刷新 UI。例如,如果您正在轮询某个服务的某些信息的更改(例如,提要的新条目),onResume()
是刷新当前视图以及(如果适用)启动后台线程来更新视图(例如,通过Handler
)的好时机。
相反,任何从您的活动中窃取用户的事情——通常是激活另一个活动——都会导致您的onPause()
方法被调用。在这里,您应该撤销您在onResume()
中所做的任何事情,比如停止后台线程、释放您可能已经获得的任何独占访问资源(例如,相机)等等。
一旦onPause()
被调用,Android 保留在任何时候终止你的活动进程的权利。因此,您不应该依赖于接收任何进一步的事件。
国家的恩惠
大多数情况下,前面提到的方法是用于处理应用级的事情(例如,在onCreate()
中把你的 UI 的最后部分连接在一起,或者在onPause()
中关闭后台线程)。
然而,Android 的很大一部分目标是拥有无缝的铜绿。活动可能根据内存需求来来去去,但理想情况下,用户不会意识到这种情况正在发生。例如,如果一个用户正在使用一个计算器,午休后又回到那个计算器,他应该会看到他在午休前正在处理的数字,除非他采取了一些措施关闭计算器(例如,按下返回按钮退出)。
为了完成所有这些工作,活动需要能够保存它们的应用实例状态,并且要快速、廉价地保存。由于活动可能在任何时候被终止,活动可能需要比您预期的更频繁地保存它们的状态。然后,当活动重新启动时,活动应该恢复到以前的状态,这样它就可以将活动恢复到以前的状态。可以把它想象成建立一个书签,这样当用户返回到该书签时,您可以将应用恢复到用户离开时的状态。
保存实例状态由onSaveInstanceState()
处理。这提供了一个Bundle
,活动可以将它们需要的任何数据(例如,计算器显示屏上显示的数字)注入其中。这个方法的实现需要很快,所以不要太花哨——只需将数据放入Bundle
中,然后退出该方法。
该实例状态在两个地方再次提供给您:在onCreate()
和onRestoreInstanceState()
中。当您希望将状态数据重新应用到活动时,这是您的选择——任一回调都是合理的选择。
onSaveInstanceState()
的内置实现将保存部件子集的可能可变状态。例如,它会将文本保存在EditText
中,但不会保存Button
是启用还是禁用的状态。只要小部件通过它们的android:id
属性被唯一识别,这就可以工作。
因此,如果您实现了onSaveInstanceState()
,您可以向上链接并利用继承的实现,或者不向上链接并覆盖继承的实现。类似地,有些活动可能根本不需要onSaveInstanceState()
来实现,因为内置的活动会处理所有需要的事情。
版权属于:月萌API www.moonapi.com,转载请注明出处