什么是ANR
通常系统无法响应用户input event时才出现ANR。例如,如果一个程序块在一些I/O操作(网络访问)在UI线程上让系统不能处理传入的用户输入事件。
或者应用程序花太多的时间构建一个复杂的内存结构或计算下一个游戏在UI线程上。总是很重要的,以确保这些计算是有效的,但是即使是最高效
的代码仍然需要时间来运行的。
在任何情况下,你的程序执行一个冗长的操作,你不应该在UI线程上执行,而是创建一个工作线程,在那里做大部分的工作。
这使UI线程(驱动用户界面事件循环)运行和防止系统认为您的代码已经冻结。
在Android中,应用程序的响应性是由ActivityManager和WindowManager系统服务监控的,ANR对话框出现的是当它检查到下面条件之一出现。
1.无响应输入事件(如键盘按下或者屏幕触摸事件)5秒内
2.广播接受者10秒内没有结束
如果避免ANR
Android应用程序完全正常运行在单个线程默认UI线程(或主线程)。这意味着任何应用程序UI线程中做需要长时间完成的任务可能触发ANR对话框。
因此,在UI线程中运行的任何方法都应该尽可能的少的工作进程,特别是长时间的操作,如网络或数据库操作等都应该通过异步请求处理。
最有效的方式创建一个工作线程继承AsyncTask类,简单的扩展AsyncTask并实现doInBackgroud()方法来执行工作,修改更新进度,你可以使用
publicProgress(),它调用onProgressUpdate()回调方法,onPostExecute()方法UI线程做出对结果的处理。
例如:
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 = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// 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[0]);
}
// This is called when doInBackground() is finished
protected void onPostExecute(Long result) {
showNotification("Downloaded " + result + " bytes");
}
}
执行工作线程,简单的实例化调用execute();
new DownloadFilesTask().execute(url1, url2, url3);
上诉是google推荐使用的操作,不过我们也经常会使用到Handler+Thread+Message模式来避免ANR,Handler模式会在下一章详细说明。