阅读此文须要对handler原理有必定的了解程度。java
Handler 原理和源码linux
首先贴出来两个知识点。app
第一 java线程能够休眠oop
第二Android只有主线程能够更新UI学习
有人以为这是傻子都知道的知识,那接下来讲傻子可能不知道的知识spa
直接叙述线程
全部java的入口都是main方法 由虚拟机调用,Android 的也不例外,刚开始学习那会根本没研究Android 从哪里开始执行的,如今我知道了告诉那些不知道的同窗,不是从application。直接看源码ActivityThread3d
看到了吗?看到了吧。对象
再来一个惊天的大幂幂blog
当main 方法执行完毕以后,程序就会退出了。
那不对啊和咱们看到的不同啊,App启动以后能够一直运行啊,怎么解释。
直接解释,App一直运行这个是没错的,也就是说明main方法并无执行完,看代码
先看3,若是main方法执行完到最后会抛一个异常,很明显咱们的App并无抛异常,那就说明Main方法没有执行完。
那怎么才能保证不会执行完毕呢?
这个问题就须要思考了,若是让我作,最早想到的就是开一个死循环,可是时间一长确定就OOM了,
其实Android 也是这么作的 ,1处的代码 里面不给你们看了 大概的逻辑内容我文字带过
建立一个惟一的Looper 对象,而后绑定一个messageQueue队列 。(不懂的能够去看handler 详解)
而后看2 代码里边就是开启了Looper循环,一个死循环无限的从消息队列中去取消息(handler源码)。
这样的话咱们的Main方法就卡在这里了,就不会执行完,程序也就是咱们看到那样,一直在运行。
刚才我说了要是我们写个死循环那估计领导就得找咱们谈谈理想了,时间一长就OOM了,那为何Android 能够这么搞呢,简单解释一下我也不懂也不深究,linux层去实现的,阻塞式循环,也就是有消息了就去执行消息,没有消息以后主线程就会休眠,前边说过了 java线程是容许休眠的(有兴趣的朋友能够去单独深究一下)
到这里了 若是你明白了这一点,就说明个人叙述能力仍是能够的(若是没懂那就多看两遍,看到懂为止 哈哈)
问题2来了
说是死循环,可是咱们的App可不是死的,使可以接受交互的。
那么问题来了 咱们正常点击的速度是确定没有程序执行快的,因此说不会有任何问题,可是若是一个点击事件当中执行了耗时操做,看下面代码
这个点击了 会ANR吗?答案是不必定,
第一种状况,若是只点击了一次,主线程休眠十秒,没有问题,十秒以后主线程执行完毕,继续阻塞式休眠。
第二种状况,若是连续点击了屡次,多个事件放到Looper 对象的MessageQueue当中 ,第一个事件去执行,主线程休眠十秒,而后第二个事件分发过来的时候,主线程还在sleep,这个时候咱们的第二个事件就一直得不到执行,超过阀值就会ANR。
阀值
按键事件 5s ,broadcast 10s、service ANR超时的定义在ActiveServices.java中,前台service无响应的超时时间为20秒,后台service为200秒
回到主题,Android 主线程looper 一直循环不会ANR
两个方面回答 第一,死循环不是形成ANR的必然缘由 ,ANR是由于消息队列当中的事件没有获得及时的处理形成的。(可是咱们写个死循环 基本上就会形成ANR,缘由就是主线程一直在这里循环 ,后面的事件没有的到及时处理。 )
第二 主线程的Looper 循环 不会ANR最多就是OOM,为何不会OOM上边解释了