读《Multitasking the Android Way》(一)
Android Developers Blog 发表了一篇题为《Multitasking the Android Way》的博文,读起来颇为有趣。我将博文中的关键信息加以自己的理解,简单整理成以下文字,以便日后查阅之便。能力有限,误读和错读难以避免,阅读者应该坚持怀疑的态度来阅读本文,尽信书不如无书。
同时运行多个应用程序,即 Multitask,对于现在的 OS 来说,是个稀松平常的事情,–IPhone OS 另当别论。Android 对 Multitask 的处理方式有着自己独到之处,这让从其他平台转来的开发者有点发懵。凡事知其然,更要知其所以然,要设计出和 Android 完美“融合”的应用程序,理解 Multitask 是非常有必要的。这篇博文从设计考量出发,告诉你问题的大环境是什么,然后讲述现在的处理机制对于应用程序的影响,最后引出开发者应该如何利用好这一机制。
移动设备,例如手机等,有着苛刻的技术限制,内存、电量、运算速度等都不能和 PC 相提并论,用户体验更不能照搬桌面软件或者 web 系统,任何试图在移动设备上建立起和 PC 相等的用户体验是一种不怎么明智的想法。
Android 设计者在设计 multitask 时充分考虑到了这些,并归纳成四点设计考量:
- 应用程序在完成后,无需关闭。
- 系统交换空间并不充裕,内存使用有苛刻的限制。
- 应用程序间切换十分关键,启动一项新应用的时间被限制在1秒之内。
- API 不仅要能满足第三方开发者,并且必须足以支持创建内置的 Google 应用,
all applications are created equal
。
很明显,前两点是冲突的。Android 淡化“关闭应用程序”这一常见的操作,相反 Android 想让用户感觉到所有的应用程序一直都在运行当中。与此同时,移动设备都有着比较苛刻的内存限制,因此一旦它需要的内存超过了可用的内存,系统就会很快变慢。这一对矛盾一直伴随着 Android 设计过程。
对 Android multitask 的一个常见误解是混淆进程和应用之间的差别。Android 里,用户可能看到了应用,实际上却没有进程在运行;多个应用可能共享一个进程,也可能一个应用使用了多个进程;应用可能没有在做任何事情,但是进程却会一直被保留。
事实上,进程正在“运行”,并不能等同应用就在运行,或者说在执行什么操作。用户离开应用,Android 会自行处置进程,如果判定稍后还需要这个它,则就会保留它,也有可能用户刚刚离开应用,Android 就清除掉了这个进程,但是这并不妨碍用户返回到刚刚离开的地方。
这种处理方式的关键是要明白进程并没有被彻底地关闭。当用户离开应用,应用进程会被保留在后台,需要的话,会允许它继续工作。如果用户返回应用,则进程立即进入到前台。假设设备从不会用完内存,那么 Android 就会保留所有的进程,并且让它们一直“运行”下去。
当然了,只有人的欲望才是无限的,机器的内存总是有限的,Android 在这一点上是非常清楚,因此它必须决定在什么时间清除掉不必要的进程。Android 会有规则来判断每一个进程的重要性以及哪一个进程应该被清除。这些规则基于两个因素:该进程对当前用户体验的重要性和距离上次使用到该进程的时间间隔有多久。
一旦 Android 决定要清除掉某个进程,那么它就会用简单粗暴的方式直接 KILL 它,同时内核会立即跟进,不管三七二十一,回收这个进程持有的所有资源。
如果用户返回到了进程已被杀死的应用,Android 需要有一种方法能够重新启动,并且恢复到此前的最后状态。通过跟踪用户关心的 Activity,记录观察到的状态信息,并使用最后的状态信息重新启动 Activity,Android 成功营造出了营造“all applications are running all of the time”的假象。用户每次离开 Activity,系统就会生成新的状态,–注意不是在进程被KILL时!正因为保留了最后的状态信息,所以内核才可以“肆无忌惮”地杀死进程。
某种意义上讲,Android 的进程管理可以被视为一种 swap space:应用进程代表了正在使用的内存的大小;当内存少了,一些进程会被杀死(相当于 swapped out);当这些进程被再次需要的时候,它们就会从最后保存的状态(swapped in)中恢复,重新启动。