Handler中Looper死循环为什么不会导致应用卡死?

}

为什么每一个应用会有自己的一个main函数呢?

当我们在launcher界面启动一个应用的时候,这时候,系统就会用zygote给我们分配一个虚拟机,然后,这个应用就会运行在这个虚拟机上面。

应用运行到虚拟机之后,首先它要执行的就是启动ActivityThread,在ActivityThread中,它又会启动它的main()函数。

在main()函数中,它最重要的两行代码:

public static void main(String[] args) {

Looper.prepareMainLooper();

Looper.loop();
}

所以在程序运行的时候,主线程所有的代码都运行在这个Looper里面。

也就是说应用所有生命周期的函数(包括Activity、Service所有生命周期)都运行在这个Looper里面,而且,它们都是以消息的方式存在的。

假如说一个Activity启动,要走onResume()函数的时候,它就会在Activity的H里面执行RESUME_ACTIVITY。

case RESUME_ACTIVITY: return “RESUME_ACTIVITY”;

它发送了一个Resume的消息,再接着看下这个Resume这个消息做了什么事情,代码在ActivityThread.java的handleMessage中。

case RESUME_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, “activityResume”);
SomeArgs args = (SomeArgs) msg.obj;
handleResumeActivity((IBinder) args.arg1, true, args.argi1 != 0, true,
args.argi3, “RESUME_ACTIVITY”);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;

进入handleResumeActivity()方法。

// TODO Push resumeArgs into the activity for consideration
r = performResumeActivity(token, clearHide, reason);

它触发了Activity的管理机制,在Activity的管理机制里面,他就会发送一个消息,这个消息,就是对Activity进行Resume的操作。

r.activity.performResume();

接着往performResume()方法里面走,就进入了Activity.java。

final void performResume() {

mFragments.dispatchResume();
mFragments.execPendingActions();


}

再后面就调用了Fragemet的管理机制。

public void dispatchResume() {
mHost.mFragmentManager.dispatchResume();
}

因为类的继承,到最终是继承自了FragmentActivity,所以最后又变成了对Fragment的Resume。

既然Handler的消息全都是loop来的,为什么我们没有ANR问题?

其实产生ANR问题的不是Looper.loop(),哪怕主线程正在等待(block)。

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

}

因为这个时候(阻塞)的时候,说明主线程在休眠。

之前不是说5秒钟不相应就会出现阻塞问题吗,为什么休眠个好长时间也并不会被ANR呢?

了解这个问题,先看唤醒主线程的方式有哪些:

1、输入事件

主线程虽然被block了,但与ANR的问题是没有关系的,只要输入事件有响应,他会唤醒,就不会被block了。

所以,产生ANR的问题不是因为主线程睡眠了,而是因为输入事件没有响应,输入事件没有响应他就没有办法唤醒这个Looper,才加了这个5秒的限制。

2、往Looper里面添加消息的时候,它会唤醒这个Looper。

因为应用中不管是Activity,还是Service,所有的操作都是在各自的生命周期中执行的,所以它所有的操作都逃不出生命周期。所以,所有的操作都执行在ActivityThread.java中的loop()里面,所以,应用所有的操作都是在这个loop()中来管理的,也正是因为这个原因,主线程的loop()是不能够退出去的。

只有一种情况,我们在一个应用的一个界面下不动,这个应用没有任何事件发生,也没有任何别的事件要处理,这个时候,我们的Looper就处于一个block状态;当点击一下这个屏幕,他就会触发唤醒这个Looper。

总结

为什么没有导致应用卡死?

因为应用卡死压根与这个Looper没有关系,应用在没有消息需要处理的时候,它是在睡眠,释放线程;卡死是ANR,而Looper是睡眠。

卡死是在主线程中执行一个耗时的操作,loop()会一直在处理一个消息,而for循环中有很多消息需要被处理,而这一个消息就要处理很久,这一个消息的处理时间,会转变成其他的点击事件没有响应。

因为主线程在接受到其他消息的时候没有时间去响应,它的时间都在处理那一个耗时的操作,造成点击事件没有办法响应,点击事件没有办法响应就容易出现ANR。

原文作者:Seas.Su
原文链接:https://blog.csdn.net/yichen97/java/article/details/106367067

最后

题外话,我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在IT学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多程序员朋友无法获得正确的资料得到学习提升,故此将并将重要的Android进阶资料包括自定义view、性能优化、MVC与MVP与MVVM三大框架的区别、NDK技术、阿里面试题精编汇总、常见源码分析等学习资料。

【Android思维脑图(技能树)】

知识不体系?这里还有整理出来的Android进阶学习的思维脑图,给大家参考一个方向。

Android开发8年,阿里、百度一面惨被吊打!我是否应该转行了?

【Android进阶学习视频】、【全套Android面试秘籍】

希望我能够用我的力量帮助更多迷茫、困惑的朋友们,帮助大家在IT道路上学习和发展
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
的力量帮助更多迷茫、困惑的朋友们,帮助大家在IT道路上学习和发展
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值