5.2.4 进程的强行终止

除了上述“正常”的途径可以进行进程回收,在一些特殊情况下,系统不得不使用一些“特别手段”来强制结束某些应用进程,以确保系统正常运行。

如果进程中的组件在运行时触发了未捕获的异常或者运行时的错误,就会导致应用进程变成异常进程,无法继续执行。此时,Android会强行终止该组件所在的进程,相比传统的进程终止方式,Android对异常进程的处理更“温柔”。组件管理服务在终止应用进程前,会保存异常发生时该进程各个任务中界面组件栈的内容,而在进程强行终止后,会重新构造新的应用进程,并将各个任务的组件栈恢复至异常发生前的状况(如图5-6所示)。

通过这种方式,Android把触发异常给用户带来的损失控制到最低,用户只会丢失掉当前界面的一些数据,而之前与其他界面组件所做的交互都将保留下来。

5.2.4 进程的强行终止 - 图1

图 5-6 异常进程的恢复

除此之外,如果应用进程中组件执行的同步操作时间过长,或者该进程对用户的操作无法及时作出回应,就会被视为无响应进程。Android会定时检查系统中各组件及其进程的执行状况,一旦发现以下状况,就会认定该应用进程失去了响应:

1)应用对用户的操作(比如按键事件、触屏事件等)超过5秒仍未处理。

2)应用进程中的触发器组件,执行BroadcastReceiver.onReceive函数的时长超过了10秒。

与异常进程不同,无响应进程虽然会影响用户体验,但并非是“非死不可”,因此,一旦有应用进程失去响应,系统就会弹出无响应对话框(ANR Dialog, Application Not Responding Dialog),询问用户是否需要强行关闭该应用进程(如图5-7所示)。如果用户选择终止,系统就会立刻尝试终止该进程,并不再尝试自动恢复;而如果用户选择继续等待,系统则会将计时清零,重新监控进程的执行状况,等到下一次无响应时,再提示用户。

5.2.4 进程的强行终止 - 图2

图 5-7 ANR(应用无响应)对话框示例

开发者应该采用异步执行等手段来执行耗时的操作,保持主线程不被阻塞,避免应用进程出现无响应的状况,以提高用户体验[1]。比如,在服务组件的Service.onStartCommand函数、触发器组件的BroadcastReceiver.onReceive等函数中,避免执行耗时的函数,如果有,可以使用独立的线程来后台执行。

[1]关于如何避免应用失去响应,可以参考SDK文档:http://developer.android.com/guide/practices/design/responsiveness.html。