线程安全方法(Thread-safe methods)
在一些情况下,你所实现的方法有可能会被多于一个的线程所调用,所以它们必须被写成线程安全的。
对于我们上一节所讨论的RPC机制中的可以被远程调用的方法来说,这是必须首先考虑的。如果针对一个IBinder对象中实现的方法的调用源自这个 IBinder对象所在的进程时,这个方法将会在调用者的线程中执行。然而,如果这个调用源自其它的进程,则这个方法将会在一个线程池中选出的线程中运 行,这个线程池由Android加以管理,并与IBinder存在于同一进程内;这个方法不会在进程的主线程内执行。反过来说,一个服务的 onBind() 方法应为服务进程的主线程所调用,而实现了由 onBind() 返回的对象(比如说,一个实现了RPC方法的Stub的子类)的方法将为池中的线程所调用。因为服务可以拥有多于一个的客户端,而同一时间,也会有多个池中的线程调用同一个IBinder方法。因此IBinder方法必须实现为线程安全的。
应用程序组件有其生命周期──由Android初始化它们以相应intent直到这个实例被摧毁。在此之间,它们有时是激活的有时则相反。或者,如果它是 一个activity,则是可为用户所见或者不能。这一节讨论了activity、服务以及广播接收器的生命周期,包括它们在生命周期中的状态、在状态之 间转变时通知你的方法、以及当这些进程被关闭或实例被摧毁时,这些状态产生的效果。
Activity生命周期(Activity lifecycle)
一个activity主要有三个状态:
* 当在屏幕前台时(位于当前任务堆栈的顶部),它是活跃或运行的状态。它就是相应用户操作的activity。
* 当它失去焦点但仍然对用户可见时,它处于暂停状态。即是:在它之上有另外一个activity。这个activity也许是透明的,或者未能完全遮蔽全屏,所以被暂停的activity仍对用户可见。暂停的activity仍然是存活状态(它保留着所有的状态和成员信息并连接至窗口管理器),但当系统处于极低内存的情况下,仍然可以杀死这个activity。
* 如果它完全被另一个activity覆盖是,它处于停止状态。它仍然保留所有的状态和成员信息。然而它不在为用户可见,所以它的窗口将被隐藏,如果其它地方需要内存,则系统经常会杀死这个activity。
当一个activity从这个状态转变到另一个状态时,它被以下列protected方法所通知:
void onCreate(Bundle savedInstanceState)
void onStart()
void onRestart()
void onResume()
void onPause()
void onStop()
void onDestroy()
调用父类(Calling into the superclass)
所有activity生命周期方法的实现都必须先调用其父类的版本。比如说:
总得来说,这七个方法定义了一个activity完整的生命周期。实现这些方法可以帮助你监察三个嵌套的生命周期循环:
* 一个activity 完整的生命周期 自第一次调用 onCreate()开始,直至调用onDestroy()为止。activity在onCreate()中设置所有“全局”状态以完成初始化,而在onDestroy()中释放所有系统资源。比如说,如果activity有一个线程在后台运行以从网络上下载数据,它会以 onCreate()<code>创建那个线程,而以</code> onDestroy()销毁那个线程。
* 一个activity的 可视生命周期自 onStart() 调用开始直到相应的 onStop()调用。在此期间,用户可以在屏幕上看到此activity,尽管它也许并不是位于前台或者正在与用户做交互。在这两个方法中,你可以管控用来向用户显示这个activity的资源。比如说,你可以在onStart() 中注册一个BroadcastReceiver 来监控会影响到你UI的改变,而在onStop() 中来取消注册,这时用户是无法看到你的程序显示的内容的。onStart() 和 onStop() 方法可以随着应用程序是否为用户可见而被多次调用。
* 一个activity的 前台生命周期 自 onResume() 调用起,至相应的 onPause()调用为止。在此期间,activity位于前台最上面并与用户进行交互。activity会经常在暂停和恢复之间进行状态转换──比如说当设备转入休眠状态或有新的activity启动时,将调用onPause() 方法。当activity获得结果或者接收到新的intent的时候会调用onResume() 方法。因此,在这两个方法中的代码应当是轻量级的。
下图展示了上述循环过程以及activity在这个过程之中历经的状态改变。着色的椭圆是activity可以经历的主要状态。矩形框代表了当activity在状态间发生改变的时候,你进行操作所要实现的回调方法。
下表详细描述了这些方法,并在activity的整个生命周期中定位了它们。
方法
描述
是否可被杀死(Killable?)
下一个
接下来始终遵循调用onStart()。
否
onStart()
在activity停止后,在再次启动之前被调用。
当activity正要变得为用户所见时被调用。
当activity转向前台时接下来调用onResume(),在activity变为隐藏时接下来调用onStop()。
onResume()
或
onStop()
在activity开始与用户进行交互之前被调用。此时activity位于堆栈顶部,并接受用户输入。
接下来始终遵循调用onPause()。
<code>onPause()</code>
当系统将要启动另一个activity时调用。此方法主要用来将未保存的变化进行持久化,停止类似动画这样耗费CPU的动作等。这一切动作应该在短时间内完成,因为下一个activity必须等到此方法返回后才会继续。
当activity重新回到前台时接下来调用onResume()。当activity变为用户不可见时接下来调用onStop()。
是
当activity不再为用户可见时调用此方法。这可能发生在它被销毁或者另一个activity(可能是现存的或者是新的)回到运行状态并覆盖了它。
如果activity再次回到前台跟用户交互则接下来调用onRestart(),如果关闭activity则接下来调用onDestroy()。
onRestart()
or
onDestroy()
无
请注意上表中可被杀死一列。它标示了在方法返回后,还没执行activity的其余代码的任意时间里,系统是否可以杀死包含此activity的进程。三个方法(onPause()、 onStop()<code>和</code>onDestroy())被标记为“是”。onPause()是三个中的第一个,它也是唯一一个在进程被杀死之前必然会调用的方法──onStop() 和 onDestroy() 有可能不被执行。因此你应该用 onPause() 来将所有持久性数据(比如用户的编辑结果)写入存储之中。
在可被杀死一列中标记为“否”的方法在它们被调用时将保护activity所在的进程不会被杀死。所以只有在onPause()<code>方法返回后到</code>onResume() 方法被调用时,一个activity才处于可被杀死的状态。在onPause()<code>再次被调用并返回之前,它不会被系统杀死。</code>
保存activity状态(Saving activity state)
当系统而不是用户自己出于回收内存的考虑,关闭了一个activity之后。用户会期望当他再次回到那个activity的时候,它仍保持着上次离开时的样子。
与onPause()或先前讨论的其它方法不同,onSaveInstanceState() 和 onRestoreInstanceState() 并不是生命周期方法。它们并不是总会被调用。比如说,Android会在activity易于被系统销毁之前调用 onSaveInstanceState(),但用户动作(比如按下了BACK键)造成的销毁则不调用。在这种情况下,用户没打算再次回到这个activity,所以没有保存状态的必要。
因为onSaveInstanceState()不是总被调用,所以你应该只用它来为activity保存一些临时的状态,而不能用来保存持久性数据。而是应该用onPause()来达到这个目的。
服务生命周期(Coordinating activities)
服务以两种方式使用:
这两种模式并不是完全分离的。你可以绑定至一个用 startService()启动的服务。比如说,一个后台音乐播放服务可以调用startService()并传递给它一个包含欲播放的音乐列表的Intent对象来启动。不久,当用户想要对播放器进行控制或者查看当前播放曲目的详情时,会启用一个activity,调用bindService()连接到服务来完成操作。在这种情况下,直到绑定连接关闭stopService() 才会真正停止一个服务。
与activity一样,服务也有一系列你可以实现以用于监控其状态变化的生命周期方法。但相对于activity要少一些,只有三个,而且,它们是public属性,并非protected:
void onCreate()
void onStart(Intent intent)
倚仗实现这些方法,你监控服务的两个嵌套的生命周期循环:
服务停止时没有相应的回调方法──不存在onStop()方法。
如果一个服务允许别的进程绑定,则它还会有以下额外的回调方法以供实现:
IBinder onBind(Intent intent)
boolean onUnbind(Intent intent)
void onRebind(Intent intent)
下图描绘了服务的回调方法。尽管图中对由startService 和startService方法启动的服务做了区分,但要记住,不论一个服务是怎么启动的,它都可能允许客户端的连接,所以任何服务都可以接受onBind()和onUnbind()调用。
广播接收器生命周期(Broadcast receiver lifecycle)
广播接收器只有一个回调方法:
void onReceive(Context curContext, Intent broadcastMsg)
拥有一个活跃状态的广播接收器的进程被保护起来而不会被杀死。但仅拥有失活状态组件的进程则会在其它进程需要它所占有的内存的时候随时被杀掉。
这种方式引出了一个问题:如果响应一个广播信息需要很长的一段时间,我们一般会将其纳入一个衍生的线程中去完成,而不是在主线程内完成它,从而保证用户交互过程的流畅。如果onReceive()衍生了一个线程并且返回,则包涵新线程在内的整个进程都被会判为失活状态(除非进程内的其它应用程序组件仍处于活跃状态),于是它就有可能被杀掉。这个问题的解决方法是令onReceive()启动一个新服务,并用其完成任务,于是系统就会知道进程中仍然在处理着工作。
下一节中,我们会讨论更多进程易误杀的问题。
进程与生命周期(Processes and lifecycles)
Android系统会尽可能长的延续一个应用程序进程,但在内存过低的时候,仍然会不可避免需要移除旧的进程。为决定保留或移除一个进程,Android 将每个进程都放入一个“重要性层次”中,依据则是它其中运行着的组件及其状态。重要性最低的进程首先被消灭,然后是较低的,依此类推。重要性共分五层,依 据重要性列表如下:
1. 前台进程是用户操作所必须的。当满足如下任一条件时,进程被认为是处于前台的:
* 一个正在与用户交互的activity使用着它提供的一个服务。
任一时间下,仅有少数进程会处于前台,仅当内存实在无法供给它们维持同时运行时才会被杀死。一般来说,在这种情况下,设备已然处于使用虚拟内存的状态,必须要杀死一些前台进程以用户界面保持响应。
2. 可视进程没有前台组件,但仍可被用户在屏幕上所见。当满足如下任一条件时,进程被认为是可视的:
* 它包含了一个绑定至一个可视的activity的服务。
可视进程依然被视为是很重要的,非到不杀死它们便无法维持前台进程运行时,才会被杀死。
5. 空进程不包含任何活动应用程序组件。这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间。系统经常会杀死这种进程以保持进程缓存和系统内核缓存之间的平衡。
Android会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别。比如说,如果一个进程中同时有一个服务和一个可视的activity,则进程会被判定为可视进程,而不是服务进程。
此外,一个进程的级别可能会由于其它进程依赖于它而升高。一个为其它进程提供服务的进程级别永远高于使用它服务的进程。比如说,如果A进程中的内容提供者 为进程B中的客户端提供服务,或进程A中的服务为进程B中的组件所绑定,则A进程最低也会被视为与进程B拥有同样的重要性。
本文转自over140 51CTO博客,原文链接:http://blog.51cto.com/over140/582308,如需转载请自行联系原作者