简介
ANR的全称是Application Not Respond,意思就是程序未响应,类似于我们在windows上见到的程序未响应。
原因
Android系统中,ActivityManagerService(简称AMS)和WindowManagerService(简称WMS)会检测App的响应时间,如果App在特定时间无法相应屏幕触摸或键盘输入时间,或者特定事件没有处理完毕,就会出现ANR。
无论是四大组件或者进程等只要发生ANR,最终都会调用AMS.appNotResponding()方法。
以下四个条件都可以造成ANR发生:
InputDispatching Timeout:5秒内无法响应屏幕触摸事件或键盘输入事件。
BroadcastQueue Timeout:在执行前台广播(BroadcastReceiver)的onReceive()函数时10秒没有处理完成,后台为60秒。
Service Timeout:前台服务20秒内,后台服务在200秒内没有执行完毕。
ContentProvider Timeout:ContentProvider的publish在10s内没进行完。
只有主线程(UI线程)才会产生ANR
必须发生某些输入事件或特定操作,比如按键或触屏等输入事件,在BroadcastReceiver或Service的各个生命周期调用函数
上述事件响应超时,不同的context规定的上限时间不同
ANR的根本原因
耗时的网络访问
大量的数据读写
数据库操作
硬件操作(比如camera)
调用thread的join()方法、sleep()方法、wait()方法或者等待线程锁的时候
service binder的数量达到上限无法和和System Server通信
system server中发生WatchDog ANR
service忙导致超时无响应
其他线程持有锁,导致主线程等待超时
其它线程终止或崩溃导致主线程一直等待
避免ANR及ANR的解决办法
主线程阻塞或主线程数据读取
避免死锁的出现;
避免在主线程执行耗时操作,所有耗时操作应新开一个子线程完成,然后再在主线程更新UI;
尽量避免在主线程query provider、不要滥用SharePreferences。
CPU满负荷,I/O阻塞
文件读写或数据库操作放在子线程异步操作。
内存不足
AndroidManifest.xml文件<applicatiion>中可以设置 android:largeHeap=”true”,以此增大App使用内存(不过不建议使用此法,从根本上防止内存泄漏,优化内存使用才是正道)
各大组件ANR
各大组件生命周期中也应避免耗时操作,注意BroadcastReciever的onRecieve()、后台Service和ContentProvider也不要执行太长时间的任务;
BroadcastReceiver要执行耗时操作时应启动一个service,将耗时操作交给service来完成;
避免在Intent Receiver里启动一个Activity,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点。如果应用程序在响应Intent广播时需要向用户展示什么,应该使用Notification Manager来实现。