零零碎碎的东西总是记不长久,仅仅学习别人的文章也只是他人咀嚼后留下的残渣。无意中发现了这个每日一道面试题,想了想如果只是简单地去思考,那么不仅会收效甚微,甚至难一点的题目自己可能都懒得去想,坚持不下来。所以不如把每一次的思考、理解以及别人的见解记录下来。不仅加深自己的理解,更要激励自己坚持下去。
ANR: application not response,应用程序没有响应。Android应用程序基于消息处理机制保证在发生输入、触摸等需要响应的事件之后,在规定的时间内没有得到有效的响应或者响应时间过长,都会发生ANR,弹出ANR对话框—等待应用或者退出应用。
Android中的响应性事件处理受到Activity Manager Service、Window Manager Service这两个系统服务的监视,所有与ANR相关的消息,都经过系统进程(system_service)的调度,然后分发给应用进程进行实际的消息处理。系统进程通过系统服务的监视,根据不同的情况限制不同的超时时长,一旦在限制的时间内得不到响应,就会调用AppNotRespondingDialog.show()显示ANR对话框。
实际上,Android的主线程,也就是用来绘制View的UI线程,是线程不安全的,所以就使用ANR原则对主线程进行限制,保证主线程在串行处理事件时保持流畅性,给用户良好的体验(比如UI的绘制工作必须在16ms内完成)。所以在主线程中的所有耗时操作(密集型cup操作、网络请求、大量IO等),都有可能发生ANR。
Android四大组件Activity、Service、BroadcastReceiver、ContentProvider都是运行在主线程中,对此定义不同的标准限制它们的响应时长:
- Service TimeOut:Service:前台Service(通知栏有显示)20s内、后台Service200s内
- BroadcastQueue TimeOut:BroadcastReceiver中,前台广播10s,后台广播60s。
- ContentProvider TimeOut:在publish中超过10s
- InputDispatching TimeOut:键盘输入事件、触摸事件5s内得不到响应
ANR监测机制: 整体的一个大致流程就是—事件开始前进行计时->进行事件处理->事件处理完,限制时间没到,移除计时,系统正常进行。事件没处理完,限制时间已到,移除计时,弹出ANR对话框
发生事件处理超时的情况有两种:
- 当前事件没有机会得到处理,主线程正在响应另外的时间,当前事件被阻塞
- 当前事件正在处理,但处理事件过长导致长时间得不到响应
ANR预防: 耗时操作在尽量子线程中操作—AsyncTask、intentService、HandlerThread,多线程操作避免死锁的出现以及快速的解决办法,还有就是UI层次的复杂绘制,尽量减少布局嵌套,如果Activity初始化需要一定的耗时,可以考虑马上显示Activity显示Dialog加载框异步加载数据。