Android 性能优化(17)UI优化:Keeping Your App Responsive 拒绝ANR
Keeping Your App Responsive
In this document
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:
产生无响应对话框的原因:
- KeyDispatchTimeout(5 seconds) --主要是类型按键或触摸事件在特定时间内无响应
- BroadcastTimeout(10 seconds) --BroadcastReceiver在特定时间内无法处理完成
- ServiceTimeout(20 secends) --小概率事件 Service在特定的时间内无法处理完成
- No response to an input event (such as key press or screen touch events) within 5 seconds.
- A
BroadcastReceiverhasn'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相关的工作。其它任务放到后台线程中,如使用 AsyncTask 或ThreadorHandlerThread。
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.
使用ThreadorHandlerThread 时要注意要把线程设置为后台的,否则它和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()orThread.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
ProgressBarin 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的更多相关文章
- Android开发之如何避免ANR(Keeping Your App Responsive)
一:什么是ANR 如果应用程序不能响应用户的输入了,那么就可以说应用ANR了. 如果需要运行一个耗时较长的操作的时候,不要把这个任务放在UI线程上运行,而是单独创建一个线程运行那些操作. 以下情况会出 ...
- Android学习笔记_52_全面了解Android开发规范:性能及UI优化
一.Android编码规范 1.java代码中不出现中文,最多注释中可以出现中文 2.局部变量命名.静态成员变量命名 只能包含字母,单词首字母出第一个外,都为大写,其他字母都为小写 3.常量命名 只能 ...
- android 性能优化
本章介绍android高级开发中,对于性能方面的处理.主要包括电量,视图,内存三个性能方面的知识点. 1.视图性能 (1)Overdraw简介 Overdraw就是过度绘制,是指在一帧的时间内(16. ...
- Android性能优化的浅谈
一.概要: 本文主要以Android的渲染机制.UI优化.多线程的处理.缓存处理.电量优化以及代码规范等几方面来简述Android的性能优化 二.渲染机制的优化: 大多数用户感知到的卡顿等性能问题的最 ...
- Android性能优化典范(二)
Google前几天刚发布了Android性能优化典范第2季的课程,一共20个短视频,包括的内容大致有:电量优化,网络优化,Wear上如何做优化,使用对象池来提高效率,LRU Cache,Bitmap的 ...
- android app性能优化大汇总(google官方Android性能优化典范 - 第2季)
Google前几天刚发布了Android性能优化典范第2季的课程,一共20个短视频,包括的内容大致有:电量优化,网络优化,Wear上如何做优化,使用对象池来提高效率,LRU Cache,Bitmap的 ...
- Android性能优化典范 - 第2季
Google发布了Android性能优化典范第2季的课程,一共20个短视频,包括的内容大致有:电量优化,网络优化,Wear上如何做优化,使用对象池来提高效率,LRU Cache,Bitmap的缩放,缓 ...
- Android 性能优化探究
使用ViewStub动态载入布局.避免一些不常常的视图长期握住引用: ViewStub的一些特点: 1. ViewStub仅仅能Inflate一次,之后ViewStub对象被置空:某个被ViewStu ...
- 【腾讯Bugly干货分享】Android性能优化典范——第6季
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/580d91208d80e49771f0a07c 导语 这里是Android性能优 ...
随机推荐
- TYVJ1716 上帝造题的七分钟
时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 裸体就意味着身体. 描述 “第一分钟,X说,要有矩阵,于是便有了一个里面写满了0的n×m矩阵.第二分钟,L说, ...
- kibana启动--nohup在关闭终端后无效&&守护进程详解
https://blog.csdn.net/ty_0930/article/details/70184705 https://blog.csdn.net/Dream_Flying_BJ/article ...
- javaweb开发页面数字过长显示科学计数法的问题
1. 检查该字段是否为double类型,如果是,请改成BigDecimal 2.如果是导出excel里面为科学计数法,原页面正常,是因为excel设置的原因,请参考https://jingyan.ba ...
- Ubuntu 16.04安装SwitchHosts
下载: https://github.com/oldj/SwitchHosts/releases 解压: unzip SwitchHosts-linux-x64_v3.3.6.5287.zip 移动: ...
- 集成学习(ensemble method)--基于树模型
bagging方法(自举汇聚法 bootstrap aggregating) boosting分类:最流行的是AdaBoost(adaptive boosting) 随机森林(random fores ...
- webpack-输出
输出(Output) 配置 output 选项可以控制 webpack 如何向硬盘写入编译文件. 注意,即使可以存在多个入口起点,但只指定一个输出配置. 用法(Usage) 在 webpack 中配置 ...
- 【Hibernate学习】 ——ORM(一)
Hibernate是一种能实现ORM的框架. ORM即Object Relational Mapping.对象关系映射.也就是将关系数据库中表的数据映射成为对象.也就是说将表与表之间的操作映射成对象与 ...
- PHP开发出来的万年历
<?php /** * PHP万年历 */ class Calendar{ protected $_table;//table表格 protected $_currentDate;//当前日期 ...
- Java实现二叉排序树的插入、查找、删除
import java.util.Random; /** * 二叉排序树(又称二叉查找树) * (1)能够是一颗空树 * (2)若左子树不空,则左子树上全部的结点的值均小于她的根节点的值 * (3)若 ...
- C中多线程开发
1 引言 线程(thread)技术早在60年代就被提出,但真正应用多线程到操作系统中去,是在80年代中期.solaris是这方面的佼佼者.传统的 Unix也支持线程的概念,可是在一个进程(proce ...