ANR全名Application Not Responding, 也就是"应用无响应". 当操作在一段时间内系统无法处理时, 系统层面会弹出上图那样的ANR对话框.

产生ANR原因

在Android里, App的响应能力是由Activity Manager和Window Manager系统服务来监控的. 通常在如下两种情况下会弹出ANR对话框:

5s内无法响应用户输入事件(例如键盘输入, 触摸屏幕等).

BroadcastReceiver在10s内无法结束.

造成以上两种情况的首要原因就是在主线程(UI线程)里面做了太多的阻塞耗时操作, 例如文件读写, 数据库读写, 网络查询等等.

如何避免ANR

知道了ANR产生的原因, 那么想要避免ANR, 也就很简单了, 就一条规则:

不要在主线程(UI线程)里面做繁重的操作.

可能产生ANR的条件

普通阻塞导致的ANR

CPU满负荷,这时候一般会在 trace中最后一句看到(100%TOTAL: 5.9% user + 4.1% kernel + 89% iowait)

内存原因(其实内存原因有可能会导致ANR, 例如如果由于内存泄露, App可使用内存所剩无几, 我们点击按钮启动一个大图片作为背景的activity, 就可能会产生ANR)

ANR的处理

针对三种不同的情况, 一般的处理情况如下

主线程阻塞的

开辟单独的子线程来处理耗时阻塞事务.

CPU满负荷, I/O阻塞的

I/O阻塞一般来说就是文件读写或数据库操作执行在主线程了, 也可以通过开辟子线程的方式异步执行.

内存不够用的

增大VM内存, 使用largeHeap属性, 排查内存泄露(这个在内存优化那篇细说吧)等.

知识点

哪些地方是执行在主线程的

Activity的所有生命周期回调都是执行在主线程的.

Service默认是执行在主线程的.

BroadcastReceiver的onReceive回调是执行在主线程的.

没有使用子线程的looper的Handler的handleMessage, post(Runnable)是执行在主线程的.

AsyncTask的回调中除了doInBackground, 其他都是执行在主线程的.

View的post(Runnable)是执行在主线程的.

使用子线程的方式有哪些

启Thread方式(继承Thread、实现Runnable接口)

使用AsyncTask

HandlerThread

IntentService

Loader

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐