Android的多任务运行机制

  Android系统以不同寻常的方式处理多个应用程序的同时运行。来自于其它不同平台的开发者或许会对这样的运行机制感到很奇怪。而理解Android多任务的运行,对于设计出可以良好运行的应用程序,以及与Android平台的其它部分进行无缝结合都具有重要意义。这篇文章说明了Android的多任务方式设计上的成因,它对应用程序运行产生的影响,还有你可以怎样更好地利用Android的这一特性。 

设计上的考虑

  手机设备有硬件工艺上的限制,还有在PC环境和web系统中未曾出现过的用户体验的需求。以下4个关键约束条件是我们在设计以及实现Android的多任务机制所遵循的:

  * 我们不需要用户在使用过应用程序后关闭它们。当涉及到与众多其它应用保持长时间的重复、简短的交互时,(使用完成后关闭)这样的模式就表现欠佳了。

  * 手机设备并不具备大量可供交换的空间(swap space),因而对内存的使用有相当严格的限制。Robert Love 有 一篇很好的文章 对这一主题进行了说明。

  * 在手机设备上应用程序间的切换是极其关键的;我们以明显少于1秒的时间内启动一个新的应用程序作为目标。当用户在较少的应用程序间切换时,比如,在观看视频时切换去查看新的短消息然后回到视频,这就显得尤为重要了。这种情况下出现一次明显的等待将很快引起用户的不满。

  * 作为我们“所有应用程序生而平等”的设计理念的一部分,利用系统可用的APIs 必须能足以写出Google内置的应用程序。这就意味着后台的音乐播放,数据同步,GPS导航,和应用下载必须与提供给第三方使用的是同一套APIs。

  前两项要求引发了一场有趣的争论。我们不想让用户担心要关闭他们的应用程序,而使得看上去所有应用程序一直在持续的运行。与此同时,手机设备对内存的使用有严格的限制,所以当一个应用需要超出系统可提供的更多的RAM时,将会降级运行或是很快运行失败;一台具有可交换空间的台式计算机,与此相反将会在页交换空间时出现运行迟缓。这些竞争性的限制条件成为了Android设计上的一个关键因素。 

应用程序何时“停止”?

  对Android多任务机制一个常见的误解就是没有很好地区分单个进程和应用(a process and an application)。在Android中它们并不是紧密耦合的实体:相对于用户开启的多个应用并不一定存在唯一一个实际承载这些应用的进程;多个应用之间可以共享进程,或者一个应用可以根据需要使用多个进程;即使这个应用不处于活动运行的状态,与这一应用程序关联的一个(或多个)进程都会由android来维护。

  你看到一个应用程序的进程“正在运行”,并不意味着这个应用正在运行或是在做其它的事情。进程的存在只能说明android在某一时刻还需要它,同时决定最好保留它以便再次用到。同样的,你可以离开应用程序一段时间然后回到原来的地方,在这期间Android可能会因为其它原因而需要终结这一进程。 

  Android采取这种方式管理应用程序的一个关键点在于进程不会被完全关闭。当用户离开一个应用时,它的进程在后台被保留下来,而允许它在需要的时候继续运行(比如下载web页面),并且在用户返回时立即回到前台。如果一个设备拥有无限的内存,那么Android将会维持所有这些进程,真正的让所有应用程序任一时刻都在运行。

  当然了,内存的使用是有限制的,为了作出平衡Android必须能决定在什么时候移除它不再需要的进程。这就产生了Android的进程生命周期(process lifecycle),它以这样的规则决定了各个进程的重要性以及下一个需要被清除的进程。这些规则是基于与当前用户体验所关联进程的重要程度,以及从用户上次使用到现在该进程经历了多长时间来共同设定的。

  一旦Android决定需要移除一个进程,它将使用蛮力简单的强制终止该进程。系统内核就能回收该进程关联的所有资源,而不依赖于应用是不是具有良好的实现,而发出交互的请求询问是否退出。允许内核立即回收应用程序的资源,可以带来极大方便以避免严重的内存耗尽情况的出现。

  如果用户随后返回到已经被终止的应用,Android需要一种方式以该应用在最后可见时的状态来重新启动它,来实现“所有的应用在任一时刻都在运行”的用户体验。Android通过追踪用户关心的应用程序的一部分(the Activities),并且以其最后可见时的状态信息来实现对它们的重新启动。这一最后状态是在每次用户离开应用程序的这一部分时生成的,而不是在应用程序被终止时产生,所以系统内核随后可以终止应用程序,而不需要在终结的时刻要求应用程序作出正确的交互响应。

  在某种程度上来看,Android的进程管理与内存空间的置换具有相同的形式:应用进程代表了一定量的正在使用中的内存;当系统内存降低,一些进程可以被终止(换出 swapped out);当再次需要这些进程时,它们可以从上次保存的状态重新启动(换入 swapped in)。 


显式的后台运行

  到现在为止,对应用程序我们有一种隐式的方式让它们在后台工作,只要Android按照它常规的内存管理方式终止这些进程。这样的方式对于在后台加载web页面一类的应用来说是没有问题的,但是如果有更高要求的应用特性要实现呢?象后台的音乐播放,数据同步,定位追踪,闹钟等等。

  对于以上的这些任务,应用程序需要有一种方式告诉Android“这时候我想要显式的运行。” 对这类应用有两种可以利用的机制,它们也代表着两种可以在应用的manifest中声明的组件:broadcast receiver 和 services

Broadcast Receiver

  BroadcastReceiver 可以让应用程序在一段限定的时间里,作为其它事件发生的结果而在后台运行。它可以被应用在构建高级特性的很多方面:例如AlarmManager 让应用程序在未来的某个确定时间里发出一个广播,而对于LocationManager当它检测到位置发生变化时就可以发送出一个广播。因为与receiver有关的信息是应用程序manifest中的一部分,Android可以发现以及启动应用程序即使它不是正处于运行状态;当然了,如果它在后台已经有了对应可用的进程,那么广播就能被高效地分发给它。

  应用程序设定了固定的时间(现在是10秒)来完成对一个广播的处理。如果它在这段时间没有执行完成,那么这个应用程序就会被认为行为异常,它的进程会被马上被置为后台运行状态,在系统需要时回收内存而被终结。

  BroadcastReceiver 非常适合于响应外部的行为来做少量的工作,如在收到一个新的GPS位置消息后给用户发布一个通告。由于应用的进程在主动接受广播时仅仅需要在场,它们具有非常轻量级的特征。又因为它们只能在确定性的时间里活动,所以在运行时就可以有很好的保证让它们的进程不被终止。

Services

  Service 让应用程序可以实现后台操作的持续运行。实际上各类服务提供的包含有很多功能,但是基于当前的讨论来说它们的基本目的就是让一个应用程序跟系统说“嘿,我想在后台能够持续的运行,直到我说已经完成了。” 应用程序对运行在其中的服务拥有显示启动和停止的控制权。

  Service提供了一种富客户机-服务器 模式,而它的使用方式是可选的。在启动了一个应用的服务后,紧接着Android简单实例化了在应用进程中的组件为其提供context。在这之后服务被怎样使用是由应用程序来决定的:它可以把所需的所有代码放到服务自身中而不与应用程序中的其它部分进行交互,调用与应用程序的其它部分共享的单例对象,如果需要从其他部分直接得到服务的实例,或是根据需要把服务放到另一个进程中用作完全的RPC调用。

  针对service 的进程管理与对broadcast receivers 的进程管理是不同的,因为一系列未被绑定的服务可能被要求运行不确定的时间。可能不会有足够的RAM来让所有请求的服务都得到运行,所以没有强力的保证可以让他们都运行。

  在RAM空间不足时,有服务寄宿的进程就会像后台进程一样被立即终结掉。然而,当条件合适的时候,Android将记得那些想要保持运行的服务,并且随后在有更多RAM空间可用时重启这些进程。例如,如果用户进入到一个需要大量RAM空间的web页面时,Android可能会同步终止其后台服务进程直到浏览器的内存需求量下降。

  Service可以通过请求将他们当成“前台”而进一步与系统协商其行为。结果就会使服务处于“请不要终结”(please don't kill)的状态,但是也要求它包含一个对用户的通告(notification)以说明它的活动运行。这对于用户主动关注的服务,如后台音乐播放或车载导航是很有用处的;当播放音乐和使用浏览器时,你总可以看见状态栏中音乐播放的图标。Android不会尝试去终止这些服务,但是作为一个折中的方案,你需要确保用户知道并可以在需要的时候显示地停止它们。 


通用组件的价值

  Android的通用broadcast receiver 和 service 组件使开发者可以打造广泛高效的后台操作,其中包括了很多最初并未考虑到的操作。在Android1.0中,它们被用来实现系统内建的以及属于Google应用专利所提供的几乎所有的后台行为:

  * 音乐播放在一个服务中运行,在用户离开该音乐应用程序时仍可以持续运转。

  * 闹钟应用程序调度一个与alarm manager关联的broadcast receiver,使其在下一次设置的时间点响铃。

  * 日历应用程序同样的为下一个日历事件调度了一个alarm 以便在合适的时候显示或更新它的通告。

  * 当有任何下载任务需要处理时,后台文件下载以服务的形式实现。

  * e-mail应用程序设置了一个alarm使其在规定的时间间隔内唤醒服务去查收任何到来的新的邮件。

  * Google应用程序自身维护了一个服务来接受来自网络推送来的通告消息;当它被告知有应用想完成象同步联系人这样的事情时,对应的就会发送广播给单个的应用。

  随着Android平台的进化,也有一些基础的组件已经用来实现很多主要的与开发者有关的新特性:

  * 输入法已经由开发者作为一个服务组件进行了实现,Android应用和管理它,目前作为IME来显示。

  * Application widgets 是broadcast receivers,在Android想要与之交互时就会发送广播给它们。这就使得app widgets 变成轻量级的,也就不需要它们关联应用的进程保持运行状态。

  * 可访问性的功能是作为服务实现的,在使用时Android保持其运行态并就用户的交互发送对应的信息给它。

  * 在Android2.0 中引入的同步适配器(Sync adapters)当有特定的数据同步需要被执行时,它作为服务运行于后台。

  * 活动壁纸也是一种服务,在用户选择壁纸后由Android开启服务。 


转载请注明出处

原文地址:http://android-developers.blogspot.com/2010/04/multitasking-android-way.html

更多相关文章

  1. Android多进程总结一:生成多进程(android:process属性)
  2. 安卓开发基础介绍
  3. Android(安卓)应用程序基础
  4. 还在杀进程?Android你不知道的那些事儿
  5. Android野史系列:4.利用 Android(安卓)Studio开发看美女应用
  6. Android开发人员的10大抱怨
  7. 如何发布你的Android应用程序
  8. 杂谈Android线程优先级
  9. android 消息机制

随机推荐

  1. Android(安卓)桌面组件【app widget】 进
  2. Android(安卓)多主题切换 (theme + style
  3. Android传感器概述(二)
  4. Android(安卓)-- Parcelable 序列化操作
  5. Android(安卓)UI编程进阶——使用Surface
  6. Android学习小Demo(5)结合Matrix跟Porperty
  7. Android全屏截图的方法,返回Bitmap并且保
  8. Data Binding Guide——google官方文档翻
  9. Android(安卓)内存优化篇 - 使用profile
  10. Android(安卓)基础知识点