在这篇文章里面,我们将要涉及到Android是如何判断一个程序没响应的(会调用ANR),ANR产生的原因和确保你的应用程序能够响应的方法。除了在 ”构建高效Android程序“一文外,这里有一系列的实例教我们如何确保我们的用户界面能够响应,但是,在深入研究这些之前,这里有一个屏幕不能响应团出来的对话框:
An ANR dialog displayed to the user.
在Android中,程序的响应性被Activity Manager和Window ManagerIn这两个系统服务所监视。当出现下列情况是,Android会认为该程序无响应:
鉴于上面对ANR的解说,让我们测试一下为什么这些会发生在我们的应用程序中以及为防止ANR如何构建你的应用程序。
在正常情况下,Android程序会完全的在一个单线程里运行。这就意味着,任何你应用程序的执行在你的主线程里超过一段时间就会导致弹出ANR对话框,因为你的应用程序没有机会去处理用户输入和broadcast操作。
因此,任何主线程的方法都不能做很复杂的处理。特别是Activity对象在它的关键生命周期函数里面不能处理太多,例如onCreate()
和onResume()
。那些潜在的需要很长时间运行的操作需要在另外的子线程中完成,例如网络或数据库操作,计算量很大的操作,如重新计算bitmap图形大小(或者在数据库操作时,使用的是异步请求)。虽然如此,但这并不意味着你的主线程应该阻塞去等待子线程的完成,也不是调用 Thread.wait()
或
Thread.sleep()
。相反的,你的主线程应该提供一个Handler给子线程去返回完成信息。通过这种方式来设计你的程序,会使你的主线程任然能够响应输入事件而避免由于5秒无响应而产生ANR对话框。其他的显示用户界面的线程也是同样的道理,它们同样要在相同的时限之内。
这种在IntentReciever执行上的特殊限制时间强调那些小的少量的处理应该按照规矩来,例如保存一个设置或者寄存一个通告。因此,在调用主线程其他方法的时候,应用程序应该去避免在BroadcastReceivers中潜在的长时间运行操作和运算。但是不是通过子线程来解决(因为BroadcastReceiver 的生命周期很短),如果在相应一个特有的广播时存在潜在的长时间运行的操作,你的应用程序开启一个服务(Service)。值得注意的是,你应该避免在一个Intent Receiver上开始一个 Activity,因为它将会产生一个新的屏幕去取代用户正在实用的屏幕。如果你的应用程序在一个Intent broadcast响应中有什么东西要给提示给用户,你应该使用 Notification Manager。
一般来说,100到200毫秒是用户在应用程序中能够感知到的极限。正如我们可以采取一些措施避免ANR,我们也可以采取一些措施增强程序的响应性。