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

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618165277)

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值