为了账号安全,请及时绑定邮箱和手机立即绑定

Looper.loop()一直死循环

标签:
Android

在android中如果主线程(UI线程)中进行耗时操作会引发ANR(Application Not Responding)异常,产生ANR的原因一般有两种:

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

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

比如onCreate()中进行了耗时操作,导致点击、触摸等不响应,就会产生ANR。为了避免ANR异常,android使用了Handler消息处理机制,让耗时操作在子线程运行,需要UI线程进行处理的操作给UI线程发送消息。

我们知道Handler发消息给UI线程就可以处理消息,UI线程维护着一个Looper和一个消息队列,Looper不停的拿消息队列的消息去分发处理。到这里问题来了:如果这么做的话,UI线程岂不是要一直死循环轮询消息队列拿消息?死循环不是造成ANR吗?

=>是的,确实是这样。

ActivityThread的main()
public static void main(String[] args) {
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
    ...
    Looper.loop();

    throw new RuntimeException("Main thread loop unexpectedly exited");
}

Looper.loop()

public static void loop() {
    final Looper me = myLooper();
    if (me == null) {
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }
    final MessageQueue queue = me.mQueue;

    // Make sure the identity of this thread is that of the local process,
    // and keep track of what that identity token actually is.
    Binder.clearCallingIdentity();
    final long ident = Binder.clearCallingIdentity();

    for (;;) {
        Message msg = queue.next(); // might block
        ...
        msg.target.dispatchMessage(msg);
        ...
        msg.recycleUnchecked();
    }
}

Looper.loop()是在死循环处理消息,如果main方法中没有looper进行循环,那么主线程一运行完毕就会退出,那才不正常了呢!?

所以,ActivityThread的main方法主要就是做消息循环,一旦退出消息循环,那么你的应用也就退出了。

那么问题重新问一遍:那为什么这个死循环不会造成ANR异常呢?

其实原因是显然的,因为Android是由事件驱动的,Looper.loop() 不断地接收事件、处理事件,每一个点击触摸或者说Activity的生命周期都是运行在 Looper.loop() 的控制之下,如果它停止了,应用也就停止了。只能是某一个消息或者说对消息的处理阻塞了 Looper.loop(),而不是 Looper.loop() 阻塞它。

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

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

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


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
移动开发工程师
手记
粉丝
33
获赞与收藏
8

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消