Android developer dev guide 应用程序基础之component lifecycles

 

2010-05-10 12:45:17

 

最后一部分,元件生命周期。终于翻译完了!

电子版已经上传,http://download.csdn.net/source/2335634

 

 

 

 

Android 开发者

应用程序基础

 

——————————————————————————————————

元件生命周期

应用元件有生命周期——从 Android 实例化它们来响应意图开始,到实例被销毁结束。期间,它们有时激活,有时停止,以活动对用户来说,有时可见有时不可见。这一部分讨论活动,服务,广播接收器的生命周期——包括它们生命中的各种状态,通知状态转换的方法,以及那些状态对于持有它们的进程被终止,实例被销毁的可能性的影响。

 

活动生命周期

活动主要有三个状态:

 

l   它在前台屏幕上时,是活跃的或者运行的 (在当前任务活动栈的顶部)。此时活动是用户动作的焦点。

l   如果它失去焦点但是仍在屏幕上可见,就是暂停的 。也就是另一个活动位于其上而该活动是可转移的或者没有覆盖全屏,所以暂停活动的某些部分可以显示出来。暂停的活动是活跃的(它保留了所有状态和成员信息,并且依然和窗口管理器相联系),但是在极低内存情况下可以被系统终止。

l   如果它被其他活动屏蔽了,就是停止的 。它仍保留所有状态和成员信息。然而,它不再对用户可见,所以它的窗口隐藏,当其他地方需要内存时通常会被系统终止。

 

如果活动是暂停的或者停止的,系统可以要求它完成(调用 finish() 方法)来释放其内存,或者简单地终止它的进程。当它再次显示给用户时,它必须完全重启并返回至先前状态。

 

当活动从状态间转换时,调用下面的保护方法来通知这种改变:

void onCreate(Bundle savedInstanceState)

void onStart()

void onRestart()

void onResume()

void onPause()

void onStop()

void onDestroy()

所以这些方法都是钩子函数,你可以重写它们来完成状态改变时的合适工作。所有活动必须实现 onCreate() 完成初始化步骤,当对象实例化时。许多活动也实现 onPause() 来实施数据的变化否则准备停止和用户的交互。

 

这七个方法一起定义了活动的整个生命周期。你能观察到有三个嵌套循环:

l   在第一次调用 onCreate() 到最后调用一次 onDestroy() 之间是活动的整个生命 。活动在 onCreate() 中完成全部“全局”状态的初始化步骤,在 onDestroy() 中释放全部剩下的资源。比如,如果它有一个线程在后台运行,下载网络数据,它可以在 onCreate() 中创建该线程,在 onDestroy() 中停止。

l   在调用 onStart() 直到相应地调用 onStop() 之间是活动的可见生命 。期间,用户可以在屏幕上看到活动,虽然它可能不在前台和用户互动。在这两个方法间,你可以维持用于显示给用户的资源。比如,你可以在 onStart() 中注册一个广播接收器 来监测影响你 UI 的变化,在 onStop() 中注销当用户不再能看到你显示的东西时。 onStart() onStop() 方法能被调用多次,使得活动在可见和隐藏中进行选择。

l   在调用 onResume() 直到相应地调用 onPause() 之间是活动的前台生命 。期间,活动位于屏幕上所有其他活动之前和用户互动。活动能频繁地在继续和暂停状态间转换——比如,当设备睡眠时或者新的活动启动时调用 onPause() ,当活动有结果或者新的意图递交时调用 onResume() 。所以这两个方法的代码应是相当轻量级的。

 

下图说明了这些循环和活动在两状态间的路径。有颜色的椭圆形是活动可能的主要状态。长方形表示回调方法,你可以实现这些方法完成活动在状态间转换的操作。

 

 

 

 

 

下表详细描述了每个方法,在活动的生命周期中定位它们:

Method

Description

Killable?

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().

No

onStart()

    

onRestart()

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

Always followed by onStart()

No

onStart()

onStart()

Called just before the activity becomes visible to the user.

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

No

onResume()
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().

No

onPause()

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 by onStop() if it becomes invisible to the user.

Yes

onResume()
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.

Yes

onRestart()
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 called finish() 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 the isFinishing() method.

Yes

nothing

 

注意上面表格中的 Killable 列。它说明系统是否能终止持有活动的进程,在该方法返回后而没有执行活动代码的其他内容时的任何时间 。三个方法( onPause() onStop() ,和 onDestroy() )标记为“是”。因为 onPause() 是三者的第一个,它是唯一在进程终止前确保能被调用的—— onStop() onDestroy() 可能不会。所以,你应当使用 onPause() 保存永久的数据(比如用户积分)。

Killable 列标记为“否”的方法在它们调用后就保护持有活动的进程不被终止。所以,活动处于可终止状态,比如,从 onPause() 返回到 onResume() 调用期间。它不会再变成可终止的直到 onPause() 再次返回。

在后面部分,进程和生命周期 ,不是在这里定义的“可终止”的活动仍然会被系统终止——但是那只会在极其缺乏资源的情况下发生。

 

保存活动状态

当系统,而不是用户,关闭活动来获取内存时,用户会想返回到活动并找回原先的状态。

在活动终止前捕获状态,你可以为活动执行 onSaveInstanceState() 方法。 Android 在活动能被销毁前调用该方法——也就是,在 onPause() 调用前。它传递给该方法一个 Bundle 对象,你可以以名称 - 值的形式记录活动的动态状态。当活动再次启动时, Bundle 传递给 onCreate() 和在 onCreate() 之后调用的一个方法, onRestoreInstanceState() ,所以两者其一可以重建捕获到的状态。

不像 onPause() 和之前讨论的其他方法, onSaveInstanceState() onRestoreInstanceState() 不是生命周期的方法。它们不常调用。比如, Android 在活动能够被系统销毁前调用 onSaveInstanceState() ,但是不会在用户动作实际销毁实例时调用(比如按下 BACK 键)。在该情况下,用户不想返回活动,所以没有必要保持状态。

因为 onSaveInstanceState() 不常调用,你应当仅用它记录活动的短暂状态,而不能存储永久数据。使用 onPause() 来存储永久数据。

 

同步活动

当一个活动开始了其他活动,它们都经历生命周期转换。一个可能暂停或停止,而另一个开始运行。有时,你可能需要来同步这些活动。

生命周期回调的顺序很好得定义了,特别是当两个活动在同一进程中时:

1.          当前活动的 onPause() 方法调用。

2.          接着,起始活动的 onCreate() onStart() ,和 onResume() 方法依次调用。

3.          然后,如果启动活动在屏幕上不可见,它的 onStop() 方法调用。

 

服务生命周期

服务可以有两种使用方法:

l   它可以启动并允许运行直到某些代码停止它或它自己停止。这种模式,它调用 Context.startService() 启动,调用 Context.stopService() 停止。它可以调用 Service.stopSelf() 或者 Service.stopSelfResult() 自己停止。停止服务只需要调用依次 stopService() ,不管调用了多少次 startService()

l   可以用它定义和输出的接口来操作它。客户建立和服务对象的连接,使用该连接调用服务。连接调用 Context.bindService() 建立,调用 Context.unbindService() 关闭。多个客户可以绑定到同一个服务。如果服务还没有启动, bindService() 可以选择性地启动它。

两种模式不是完全分离的。你可以绑定到由 startService() 启动的服务。比如,背景音乐可以通过传递一个指明播放的音乐的意图对象给 startService() 来启动。接下来,可能当用户想要控制播放器或者得到当前音乐的信息时,活动就可以调用 bindService() 建立到该服务的连接。这种情况下, stopService() 不会停止服务直到最后一个绑定关闭。

和活动一样,服务有生命周期方法可以用来监测状态的改变。但是比活动的方法少——只有三个——而且他们是公开的,不是保护的:

void onCreate()

void onStart(Intent intent)

void onDestroy()

实现这些方法,你可以监测到服务生命周期的两个嵌套循环:

l   在调用 onCreate() onDestroy() 返回之间是服务的整个生命 。和活动一样,服务在 onCreate() 中完成初始化步骤,在 onDestroy() 中释放所有剩下的资源。比如,背景音乐播放服务在 onCreate() 中创建播放音乐的线程,在 onDestroy() 中停止该线程。

l   调用 onStart() 开始服务的活跃生命 。该方法获得传递给 startService() 的意图对象。音乐服务打开意图获得要播放的音乐,然后开始循环播放。

服务停止时没有等价的回调——没有 onStop() 方法。

所有服务都调用 onCreate() onDestroy() ,不管他们是由 Context.startService() 还是 Context.bindService() 启动的。然而,只有 startService() 启动的服务调用 onStart()

如果服务允许绑定,就有额外的回调方法来执行:

IBinder onBind(Intent intent)

boolean onUnbind(Intent intent)

void onRebind(Intent intent)

传递给 bindService 的意图对象传递给 onBind() 回调,传递给 unbindService() 的意图传递给 onUnbind() 。如果服务允许绑定, onBind() 返回通信通道给客户和服务交流。如果新的客户连接到服务, onUnbind() 方法可以请求调用 onRebind() 方法。

下图说明了服务的回调方法。虽然,分离了通过 startService bindService() 创建的服务,但是记住任何服务,无论它们如何启动,都允许客户绑定,所以任何服务都可以接受 onBind() onUnbind() 调用。

 

 

广播接收器生命周期

广播接收器有一个回调方法:

void onReceive(Context curContext, Intent broadcastMsg)

当广播消息到达接收器时, Android 调用它的 onReceive() 方法,传递包含消息的意图对象给它。广播接收器只有当它执行这个方法时是活跃的。 onReceive() 返回后,它是未激活的。

持有活跃的广播接收器的进程是不能被终止的。但是只持有未激活元件的进程可以在任何时间被系统终止,只要它消耗的内存有其他进程需要。

这里就有一个问题,当对广播消息的响应是时间消耗的,所以工作须在分离的线程中完成,而不是其他用户界面元件运行的主线程。如果 onReceive() 产生了线程并返回,整个进程,包括新产生的线程都被认为是未激活的(除非其他进程中的应用元件是活跃的),使整个进程处于可以被终止的危险中。解决的方法是 onReceive() 启动一个服务,让这个服务来完成工作,这样系统就知道在进程中仍有工作进行。

下面部分有更多关于可以终止进程的内容。

 

进程和生命周期

Android 系统想要维持进程足够长时间,但是当内存低时进程最终会被移除。为了确定哪些进程保留,哪些进程终止, Android 安排了每个进程“重要性等级”,根据它的元件和元件的状态。最低重要性的进程首先被终止,由低到高依次进行。有五个重要性等级。下面按次序列出:

1.          前台进程 ,用户当前工作需要的进程。下面情况发生时可以认为进程是在前台的:

l   它在运行用户正在交互的活动(活动对象的 onResume() 已调用)。

l   它持有的服务和用户正在交互的活动绑定。

l   它有服务对象在执行生命周期回调( onCreate() onStart() ,或者 onDestroy() )。

l   它有广播接收器 对象在执行 onReceive() 方法。

任何时候只有一部分前台程序存在。它们只有在一种情况下会终止——如果内存低到它们无法继续运行。一般的,此时设备到达内存分页状态,所以需要终止前台进程保持用户界面响应。

2.          可见进程 ,没有前台元件但是仍可以影响用户在屏幕上可见内容的进程。下面了情况发生时可以认为进程是可见的:

l   它持有的活动不在前台,但是仍对用户可见(活动的 onPause() 方法调用)。这种情况发生,比如,如果前台活动是一个对话框,可以透过它看到前一个活动。

l   它持有一个服务绑定到可见活动。

可见进程非常重要,不可以终止,除非必须这样来保持前台进程运行。

3.          服务进程 ,运行由 startService() 方法启动的服务,又不属于前面两个类型的进程。虽然服务进程不和用户可见的东西连接,但是他们一般都在进行用户关心的工作(比如播放背景音乐或者下载网络数据),所以系统让它们保持运行,除非内存不够前两类进程运行。

4.          后台进程 ,持有当前对用户不可见的活动的进程(活动对象的 onStop() 方法调用)。这些进程对用户体验没有直接影响,能随时终止为前台,可见,或者服务进程腾出内存。通常,有许多后台进程运行,所以它们保留在 LRU (最近最少使用)列表中,保证最近用过活动的进程最后终止。如果活动正确执行生命周期的方法,并捕获它当前的状态,那么终止它不会对用户体验有负面影响。

5.          空进程 ,没有持有任何活跃应用元件的进程。唯一保留这种进程的原因是作为加快下次元件运行启动时间的缓存。系统经常终止这些进程来平衡系统进程缓存和内核缓存资源。

Android 根据进程中活跃元件的重要性给进程归类到尽可能高的级别。比如,如果进程持有一个服务和一个可见活动,进程被归类为可见进程,而不是服务进程。

另外,进程等级会因为其他进程对它的依赖而增加。服务其他进程的进程不能比它所服务的进程等级低。比如,如果进程 A 的内容供给服务进程 B 的客户,或者进程 A 的服务绑定到进程 B 的元件,那么进程 A 至少和进程 B 一样重要。

因为运行服务的进程比有后台活动的进程等级高,所以活动为长时间运行的操作启动服务可以比简单地产生线程做的更好——特别是如果该操作比活动维持的时间还要长。例子有播放背景音乐和上传照片到网站。使用服务保证了操作至少是“服务进程”的优先级,不管活动的情况如何。和前面广播接收器生命周期 部分一样,广播接收器也应该使用服务而不是把时间消耗的操作放入线程中。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值