android-项目篇-性能优化之卡顿与ANR

ANR

即使编写出能够通过世界上的所有性能测试的代码,却仍有可能让用户感觉迟钝、发生挂起或卡住很长时间,或者处理输入的时间过长。在应用响应能力方面可能发生的最糟糕的情况就是“应用无响应”(ANR) 对话框。

在 Android 中,系统会通过显示说明应用已停止响应的对话框来防范在一段时间内响应不足的应用。此时,应用已在相当长的一段时间内没有响应,因此系统会向用户提供退出此应用的选项。在设计应用时应充分考虑响应能力,让系统永远不会向用户显示 ANR 对话框,这一点至关重要。

什么会触发ANR?

当应用无法响应用户输入时,系统即会显示 ANR。

在您的应用面临任何可能需要执行冗长的操作的情况下,您不应在主线程中执行这些操作,而是应该创建工作线程并在其中执行大部分操作。这样即可让主线程(用于驱动界面事件循环)保持运行,并阻止系统断定您的代码已卡住。

在 Android 中,应用响应性由 Activity 管理器和窗口管理器系统服务监控。当 Android 检测到以下某一项条件时,便会针对特定应用显示 ANR 对话框:

  • 在 5 秒内对输入事件(例如按键或屏幕轻触事件)没有响应。
  • BroadcastReceiver 在 10 秒后尚未执行完毕。

怎么避免ANR?

Android 应用通常完全在单个线程中运行(默认为“界面线程”或“主线程”)。这意味着应用在界面线程中执行的任何需要很长时间才能完成的操作都可能会触发 ANR 对话框,因为应用没有给自己处理输入事件或 intent 广播的机会。因此,在界面线程中运行的所有方法都应该尽可能减少在此线程中的操作。

为耗时较长的操作创建工作线程的最有效方法是使用 AsyncTask 类。只需扩展 AsyncTask 并实现 doInBackground() 方法即可执行相应操作。要向用户发布进度变化,您可以调用 publishProgress(),它会调用 onProgressUpdate() 回调方法。通过 onProgressUpdate()(在界面线程中运行)的实现,您可以向用户发送通知。

虽然比 AsyncTask 复杂,但您可能想要创建自己的 Thread 或 HandlerThread 类。如果是这样,您应该调用 Process.setThreadPriority() 并传递 THREAD_PRIORITY_BACKGROUND,从而将线程优先级设为“后台”优先。如果您不通过这种方式将线程设为较低的优先级,则此线程仍可能会让应用变慢,因为默认情况下,此线程会按照与界面线程相同的优先级操作。

通常,100 到 200 毫秒是一个阈值,一旦超出此阈值,用户便能够感受到应用速度缓慢。

参考

  • 开发者指南

你可能感兴趣的:(android)