您的位置:首页 > 移动开发 > Android开发

Android ANR产生原因和相关解决方案浅析

2018-02-23 17:53 288 查看
做过Android开发的朋友们肯定都听过或者时常碰到ANR问题,那么什么是ANR?Android为什么要引入ANR这个概念呢?ANR是怎样产生的?如何才能避免ANR问题呢?
1.什么是ANR?
ANR:全称application not responding,即应用程序无响应,类似于我们在windows上见到的程序未响应;

2.Android中为什么要引入这个概念呢 ?
众所周知,Android系统是单线程模型,应用一旦发生ANR,系统会提示,并且告知用户是否等待或者关闭两种选择操作,无论是等待还是关闭,对用户来说都是很不友好的。等待吧,谁也不知道要等多久,关闭吧,当前处理的事情还没有处理完,关闭有需要重新启动,耗电耗流量还耗时间,更重要的是这个极大地挑战了用户的耐心,增加了我们的应用被用户抛弃的风险。
因为Android系统是单线程模型,所以考虑到某些应用不规范的开发(耗时操作运行在UI线程)导致系统长时间无响应,避免让用户误认为是系统卡顿的问题,故引入ANR这个概念,用来明确告知用户当前无响应并非系统问题,而是当前正在使用的或者系统中安装的那个应用阻塞了UI线程才产生的,我想这就是Google引入这个概念的一个原因吧。(注:个人理解,如有不同见解,欢迎交换,共同成长)

了解了什么是ANR以及ANR的来源,下面才是我们本篇的重点内容!!!

3.ANR是如何产生的?
ANR发生是有条件的,只有满足了以下其中一个条件,才会产生ANR,那么是什么条件呢?请看下面

1.只有主线程才会产生ANR,主线程就是UI线程;
2.必须发生在某些输入事件或特定操作,比如按键或触屏等输入事件,以及BroadcastReceiver或Service的各个生命周期调用函数;
3.上述事件响应超时,不同的context规定的上限时间不同
    a.主线程对输入事件5秒内没有处理完毕
    b.主线程在执行BroadcastReceiver的onReceive()函数时10秒内没有处理完毕
    c.主线程在Service的各个生命周期函数时20秒内没有处理完毕。

那么导致ANR的根本原因是什么呢?简单的总结有以下两点:
1.主线程执行了耗时操作,比如数据库操作、文件操作或网络编程等
2.其他进程(就是其他程序)占用CPU导致本进程得不到CPU时间片,比如其他进程的频繁读写操作可能会导致这个问题。

细分的话,导致ANR的原因有如下几点:
1.耗时的网络访问
2.大量的数据读写
3.数据库操作
4.硬件操作(比如camera)
5.调用thread的join()方法、sleep()方法、wait()方法或者等待线程锁的时候
6.service binder的数量达到上限(网上查资料得知是15个,具体有待考证)
7.system server中发生WatchDog ANR
8.service忙导致超时无响应
9.其他线程持有锁,导致主线程等待超时
10.其它线程终止或崩溃导致主线程一直等待

通过上面内容我们了解了ANR产生的原因,想必大家也清楚了如何避免ANR问题
4.避免ANR的部分手段(欢迎补充)
1.避免在主线程执行耗时操作,所有耗时操作应新开一个子线程完成,然后再在主线程更新UI。
2.BroadcastReceiver要执行耗时操作时应启动一个非工作线程或者service等,将耗时操作交给非工作线程或者service来完成(service也是同步的,耗时操作必须在非工作线程中进行)。
3.避免在Intent Receiver里启动一个Activity,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点。如果你的应用程序在响应Intent广 播时需要向用户展示什么,你应该使用Notification Manager来实现。
4.service各个生命周期中如有耗时操作,也需要在子线程中操作。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: