Keeping Your App Responsive

  

  Figure 1. An ANR dialog displayed to the user.

  It's possible to write code that wins every performance test in the world, but still feels sluggish, hang or freeze for significant periods, or take too long to process input. The worst thing that can happen to your app's responsiveness is an "Application Not Responding" (ANR) dialog.

  In Android, the system guards against applications that are insufficiently responsive for a period of time by displaying a dialog that says your app has stopped responding, such as the dialog in Figure 1. At this point, your app has been unresponsive for a considerable period of time so the system offers the user an option to quit the app. It's critical to design responsiveness into your application so the system never displays an ANR dialog to the user.

  This document describes how the Android system determines whether an application is not responding and provides guidelines for ensuring that your application stays responsive.

What Triggers ANR? 什么是无响应对话框


  Generally, the system displays an ANR if an application cannot respond to user input. For example, if an application blocks on some I/O operation (frequently a network access) on the UI thread so the system can't process incoming user input events. Or perhaps the app spends too much time building an elaborate in-memory structure or computing the next move in a game on the UI thread. It's always important to make sure these computations are efficient, but even the most efficient code still takes time to run.

  In any situation in which your app performs a potentially lengthy operation, you should not perform the work on the UI thread, but instead create a worker thread and do most of the work there. This keeps the UI thread (which drives the user interface event loop) running and prevents the system from concluding that your code has frozen. Because such threading usually is accomplished at the class level, you can think of responsiveness as a classproblem. (Compare this with basic code performance, which is a method-level concern.)

  In Android, application responsiveness is monitored by the Activity Manager and Window Manager system services. Android will display the ANR dialog for a particular application when it detects one of the following conditions:

 产生无响应对话框的原因:
  1. KeyDispatchTimeout(5 seconds) --主要是类型按键或触摸事件在特定时间内无响应
  2. BroadcastTimeout(10 seconds) --BroadcastReceiver在特定时间内无法处理完成
  3. ServiceTimeout(20 secends) --小概率事件 Service在特定的时间内无法处理完成
  • No response to an input event (such as key press or screen touch events) within 5 seconds.
  • BroadcastReceiver hasn't finished executing within 10 seconds.

How to Avoid ANRs 避免无响应对话框的方法


  Android applications normally run entirely on a single thread by default the "UI thread" or "main thread"). This means anything your application is doing in the UI thread that takes a long time to complete can trigger the ANR dialog because your application is not giving itself a chance to handle the input event or intent broadcasts.

  Therefore, any method that runs in the UI thread should do as little work as possible on that thread. In particular, activities should do as little as possible to set up in key life-cycle methods such as onCreate() and onResume(). Potentially long running operations such as network or database operations, or computationally expensive calculations such as resizing bitmaps should be done in a worker thread (or in the case of databases operations, via an asynchronous request).

  The most effective way to create a worker thread for longer operations is with the AsyncTask class. Simply extend AsyncTask and implement the doInBackground() method to perform the work. To post progress changes to the user, you can call publishProgress(), which invokes the onProgressUpdate() callback method. From your implementation of onProgressUpdate() (which runs on the UI thread), you can notify the user. For example:

 通常使用避免ANR的方法就是在ui线程中只做与ui相关的工作。其它任务放到后台线程中,如使用 AsyncTaskThread or HandlerThread 。
 private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
// Do the long-running work in here
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = ;
for (int i = ; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * ));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
} // This is called each time you call publishProgress()
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[]);
} // This is called when doInBackground() is finished
protected void onPostExecute(Long result) {
showNotification("Downloaded " + result + " bytes");
}
}

  To execute this worker thread, simply create an instance and call execute():

new DownloadFilesTask().execute(url1, url2, url3);

  Although it's more complicated than AsyncTask, you might want to instead create your own Thread or HandlerThread class. If you do, you should set the thread priority to "background" priority by calling Process.setThreadPriority() and passing THREAD_PRIORITY_BACKGROUND. If you don't set the thread to a lower priority this way, then the thread could still slow down your app because it operates at the same priority as the UI thread by default.

 使用 Thread or HandlerThread 时要注意要把线程设置为后台的,否则它和ui线程优先级相同,同样会产生ANR.
 代码 Process.setThreadPriority(THREAD_PRIORITY_BACKGROUND); 设置后台。

  If you implement Thread or HandlerThread, be sure that your UI thread does not block while waiting for the worker thread to complete—do not call Thread.wait() or Thread.sleep(). Instead of blocking while waiting for a worker thread to complete, your main thread should provide a Handler for the other threads to post back to upon completion. Designing your application in this way will allow your app's UI thread to remain responsive to input and thus avoid ANR dialogs caused by the 5 second input event timeout.

 不要在ui线程中,调用 Thread.wait() or Thread.sleep() 等待工作线程完成工作。如要它们之间有数据传输,可以使用 Handler

  The specific constraint on BroadcastReceiver execution time emphasizes what broadcast receivers are meant to do: small, discrete amounts of work in the background such as saving a setting or registering a Notification. So as with other methods called in the UI thread, applications should avoid potentially long-running operations or calculations in a broadcast receiver. But instead of doing intensive tasks via worker threads, your application should start an IntentService if a potentially long running action needs to be taken in response to an intent broadcast.

 BroadcastReceiver 同样可以使用工作线程减少阻塞。

  Tip: You can use StrictMode to help find potentially long running operations such as network or database operations that you might accidentally be doing on your main thread.

Reinforce Responsiveness 其它避免ANR的技巧


  Generally, 100 to 200ms is the threshold beyond which users will perceive slowness in an application. As such, here are some additional tips beyond what you should do to avoid ANR and make your application seem responsive to users:

  • If your application is doing work in the background in response to user input, show that progress is being made (such as with a ProgressBar in your UI).
  • For games specifically, do calculations for moves in a worker thread.
  • If your application has a time-consuming initial setup phase, consider showing a splash screen or rendering the main view as quickly as possible, indicate that loading is in progress and fill the information asynchronously. In either case, you should indicate somehow that progress is being made, lest the user perceive that the application is frozen.
  • Use performance tools such as Systrace and Traceview to determine bottlenecks in your app's responsiveness.

Android 性能优化(17)UI优化:Keeping Your App Responsive 拒绝ANR的更多相关文章

  1. Android开发之如何避免ANR(Keeping Your App Responsive)

    一:什么是ANR 如果应用程序不能响应用户的输入了,那么就可以说应用ANR了. 如果需要运行一个耗时较长的操作的时候,不要把这个任务放在UI线程上运行,而是单独创建一个线程运行那些操作. 以下情况会出 ...

  2. Android学习笔记_52_全面了解Android开发规范:性能及UI优化

    一.Android编码规范 1.java代码中不出现中文,最多注释中可以出现中文 2.局部变量命名.静态成员变量命名 只能包含字母,单词首字母出第一个外,都为大写,其他字母都为小写 3.常量命名 只能 ...

  3. android 性能优化

    本章介绍android高级开发中,对于性能方面的处理.主要包括电量,视图,内存三个性能方面的知识点. 1.视图性能 (1)Overdraw简介 Overdraw就是过度绘制,是指在一帧的时间内(16. ...

  4. Android性能优化的浅谈

    一.概要: 本文主要以Android的渲染机制.UI优化.多线程的处理.缓存处理.电量优化以及代码规范等几方面来简述Android的性能优化 二.渲染机制的优化: 大多数用户感知到的卡顿等性能问题的最 ...

  5. Android性能优化典范(二)

    Google前几天刚发布了Android性能优化典范第2季的课程,一共20个短视频,包括的内容大致有:电量优化,网络优化,Wear上如何做优化,使用对象池来提高效率,LRU Cache,Bitmap的 ...

  6. android app性能优化大汇总(google官方Android性能优化典范 - 第2季)

    Google前几天刚发布了Android性能优化典范第2季的课程,一共20个短视频,包括的内容大致有:电量优化,网络优化,Wear上如何做优化,使用对象池来提高效率,LRU Cache,Bitmap的 ...

  7. Android性能优化典范 - 第2季

    Google发布了Android性能优化典范第2季的课程,一共20个短视频,包括的内容大致有:电量优化,网络优化,Wear上如何做优化,使用对象池来提高效率,LRU Cache,Bitmap的缩放,缓 ...

  8. Android 性能优化探究

    使用ViewStub动态载入布局.避免一些不常常的视图长期握住引用: ViewStub的一些特点: 1. ViewStub仅仅能Inflate一次,之后ViewStub对象被置空:某个被ViewStu ...

  9. 【腾讯Bugly干货分享】Android性能优化典范——第6季

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/580d91208d80e49771f0a07c 导语 这里是Android性能优 ...

随机推荐

  1. 【PowerDesigner】PowerDesigner之CDM、PDM、SQL之间转换

    有关CDM.PDM.SQL之间转换以及不同数据库之间库表Sql的移植,首先要了解的是它们各自的用途.这里就简单的描述一下,不做详细的解释了. CDM:概念数据模型.CDM就是以其自身方式来描述E-R图 ...

  2. Devu and Flowers lucas定理+容斥原理

    Devu wants to decorate his garden with flowers. He has purchased n boxes, where the i-th box contain ...

  3. 服务器Centos7.4 下jdk1.8环境配置、mysql环境搭建,mysql找回(重置)密码看这篇就够了

    最近一直帮我的同学搭建自己的服务器,其中涉及到了以下知识点,经过查询博客资料等方式,再加上多重实践,我成功总结出了完整的配置一个简单服务器环境的步骤: (来自 ZYXS 的CSDN 博客 ,全文地址请 ...

  4. [bzoj2229][Zjoi2011]最小割_网络流_最小割树

    最小割 bzoj-2229 Zjoi-2011 题目大意:题目链接. 注释:略. 想法: 在这里给出最小割树的定义. 最小割树啊,就是这样一棵树.一个图的最小割树满足这棵树上任意两点之间的最小值就是原 ...

  5. hadoop(2)hadoop配置

    hadoop入门(二) hadoop的配置 1.本地模式 2.伪分布式 3.分布式     一.配置linux环境: 1打开虚拟网络编辑器,选择 VMnet1 仅主机模式, 子网 IP 设为 192. ...

  6. server证书安装配置指南(Tomcat 6)

    一.   生成证书请求   1.  安装JDK 安装Tomcat须要JDK支持. 假设您还没有JDK的安装.则能够參考 Java SE Development Kit (JDK) 下载. 下载地址: ...

  7. JavaSE入门学习5:Java基础语法之keyword,标识符,凝视,常量和变量

    一keyword keyword概述:Java语言中有一些具有特殊用途的词被称为keyword.keyword对Java的编译器有着特殊的意义.在程 序中应用时一定要谨慎. keyword特点:组成k ...

  8. java并发编程之Semaphore

    信号量(Semaphore).有时被称为信号灯.是在多线程环境下使用的一种设施, 它负责协调各个线程, 以保证它们可以正确.合理的使用公共资源. 一个计数信号量.从概念上讲,信号量维护了一个许可集.如 ...

  9. Mycat(5):聊天消息表数据库按月分表实践,平滑扩展

    本文的原文连接是: http://blog.csdn.net/freewebsys/article/details/47003577 未经博主同意不得转载. 1,业务需求 比方一个社交软件,比方像腾讯 ...

  10. Matplotlib作图基础

    折线图 import matplotlib.pylab as pylab import numpy as npy x=[1,2,3,4,8] y=[5,7,2,1,5] #折线图 pylab.plot ...