在Android里, App的响应能力是由Activity Manager和Window Manager系统服务来监控的. 在主线程(UI线程)里面做了太多的阻塞耗时操作, 例如文件读写, 数据库读写, 网络查询等等.
ANR一般有三种类型
1. KeyDispatchTimeout(5 seconds) –主要是类型按键或触摸事件在特定时间内无响应
2. BroadcastTimeout(10 seconds) –BroadcastReceiver在特定时间内无法处理完成
3. ServiceTimeout(20 secends) –小概率事件 Service在特定的时间内无法处理完成
哪些操作会导致ANR 在主线程执行以下操作:
1. 高耗时的操作,如图像变换
2. 磁盘读写,数据库读写操作
3. 大量的创建新对象
3、如何避免
不要在主线程(UI线程)里面做繁重的操作.
- UI线程尽量只做跟UI相关的工作
- 耗时的操作(比如数据库操作,I/O,连接网络或者别的有可能阻塞UI线程的操作)把它放在单独的线程处理
- 尽量用Handler来处理UIThread和别的Thread之间的交互
4、解决的逻辑 - 使用AsyncTask
a. 在doInBackground()方法中执行耗时操作
b. 在onPostExecuted()更新UI - 使用Handler实现异步任务
a. 在子线程中处理耗时操作
b. 处理完成之后,通过handler.sendMessage()传递处理结果
c. 在handler的handleMessage()方法中更新UI
d. 或者使用handler.post()方法将消息放到Looper中
3.1 哪些地方是执行在主线程的
1. Activity的所有生命周期回调都是执行在主线程的.
2. Service默认是执行在主线程的.
3. BroadcastReceiver的onReceive回调是执行在主线程的.
4. 没有使用子线程的looper的Handler的handleMessage, post(Runnable)是执行在主线程的.
5. AsyncTask的回调中除了doInBackground, 其他都是执行在主线程的.
6. View的post(Runnable)是执行在主线程的.
●
● 主线程被IO操作(从4.0之后网络IO不允许在主线程中)阻塞。
● 主线程中存在耗时的计算
● 主线程中错误的操作,比如Thread.wait或者Thread.sleep等 Android系统会监控程序的响应状况,一旦出现下面两种情况,则弹出ANR对话框
● 应用在5秒内未响应用户的输入事件(如按键或者触摸)
● BroadcastReceiver未在10秒内完成相关的处理
● Service在特定的时间内无法处理完成 20秒
● 使用AsyncTask处理耗时IO操作。
● 使用Thread或者HandlerThread时,调用Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)设置优先级,否则仍然会降低程序响应,因为默认Thread的优先级和主线程相同。
● 使用Handler处理工作线程结果,而不是使用Thread.wait()或者Thread.sleep()来阻塞主线程。
● Activity的onCreate和onResume回调中尽量避免耗时的代码
● BroadcastReceiver中onReceive代码也要尽量减少耗时,建议使用IntentService处理。