android 主线程死循环,主线程中Looper的轮询死循环为什么没有阻塞主线程?

  • Post author:
  • Post category:其他


正如咱们所知,在android中若是主线程中进行耗时操做会引起ANR(Application Not Responding)异常。oop

形成ANR的缘由通常有两种:性能

当前的事件没有机会获得处理(即主线程正在处理前一个事件,没有及时的完成或者looper被某种缘由阻塞住了)

当前的事件正在处理,但没有及时完成

为了不ANR异常,android使用了Handler消息处理机制。让耗时操做在子线程运行。spa

所以产生了一个问题,主线程中的Looper.loop()一直无限循环检测消息队列中是否有新消息为何不会形成ANR?线程

while (true) {

//取出消息队列的消息,可能会阻塞

Message msg = queue.next(); // might block

//解析消息,分发消息

msg.target.dispatchMessage(msg);

}

显而易见的,若是main方法中没有looper进行循环,那么主线程一运行完毕就会退出。code

总结:ActivityThread的main方法主要就是作消息循环,一旦退出消息循环,那么你的应用也就退出了。生命周期

由于Android 的是由事件驱动的,looper.loop() 不断地接收事件、处理事件,每个点击触摸或者说Activity的生命周期都是运行在 Looper.loop() 的控制之下,若是它中止了,应用也就中止了。只能是某一个消息或者说对消息的处理阻塞了 Looper.loop(),而不是 Looper.loop() 阻塞它。队列

也就说咱们的代码其实就是在这个循环里面去执行的,固然不会阻塞了。事件

若是某个消息处理时间过长,好比你在onCreate(),onResume()里面处理耗时操做,那么下一次的消息好比用户的点击事件不能处理了,整个循环就会产生卡顿,时间一长就成了ANR。get

并且主线程Looper从消息队列读取消息,当读完全部消息时,主线程阻塞。子线程往消息队列发送消息,而且往管道文件写数据,主线程即被唤醒,从管道文件读取数据,主线程被唤醒只是为了读取消息,当消息读取完毕,再次睡眠。所以loop的循环并不会对CPU性能有过多的消耗。

总结:Looer.loop()方法可能会引发主线程的阻塞,但只要它的消息循环没有被阻塞,能一直处理事件就不会产生ANR异常。