Android-Looper

 我来答
隐曼情3
2022-07-13 · TA获得超过2949个赞
知道小有建树答主
回答量:3848
采纳率:99%
帮助的人:193万
展开全部
Looper.loop是一个死循环,拿不到需要处理的Message就会阻塞,那在UI线程中为什么不会导致ANR?

首先我们来看造成ANR的原因:
1.当前的事件没有机会得到处理(即主线程正在处理前一个事件,没有及时的完成或者looper被某种原因阻塞住了)
2.当前的事件正在处理,但没有及时完成

我们再来看一下APP的入口ActivityThread的main方法:

显而易见的,如果main方法中没有looper进行死循环,那么主线程一运行完毕就会退出,会导致直接崩溃,还玩什么!

现在我们知道了消息循环的必要性,那为什么这个死循环不会造成ANR异常呢?

我们知道Android 的是由事件驱动的,looper.loop() 不断地接收事件、处理事件,每一个点击触摸或者说Activity的生命周期都是运行在 Looper的控制之下,如果它停止了,应用也就停止了。只能是某一个消息或者说对消息的处理阻塞了 Looper.loop(),而不是 Looper.loop() 阻塞它,这也就是我们为什么不能在UI线程中处理耗时操作的原因。
主线程Looper从消息队列读取消息,当读完所有消息时,主线程阻塞。子线程往消息队列发送消息,唤醒主线程,主线程被唤醒只是为了读取消息,当消息读取完毕,再次睡眠。因此loop的循环并不会对CPU性能有过多的消耗。

初始化当前线程和Looper,这样可以在实际开始启动循环(loop())之前创建一个Handler并且关联一个looper。确保在先调用这个方法,然后调用loop()方法,并且通过调用quit()结束。

这里面的入参boolean表示Looper是否允许退出,true就表示允许退出,对于false则表示Looper不允许退出。

初始化当前当前线程的looper。并且标记为一个程序的主Looper。由Android环境来创建应用程序的主Looper。因此这个方法不能由咱们来调用。另请参阅prepare()

这里的sThreadLocal.get()是和prepare(boolean)方法里面的sThreadLocal.set(new Looper(quitAllowed));一一对应的。而在prepareMainLooper()方法里面。

退出循环
将终止(loop()方法)而不处理消息队列中的任何更多消息。在调用quit()后,任何尝试去发送消息都是失败的。例如Handler.sendMessage(Message)方法将返回false。因为循环终止之后一些message可能会被无法传递,所以这个方法是不安全的。可以考虑使用quitSafely()方法来确保所有的工作有序地完成。

安全退出循环
调用quitSafely()方法会使循环结束,只要消息队列中已经被传递的所有消息都将被处理。然而,在循环结束之前,将来不会提交处理延迟消息。
调用退出后,所有尝试去发送消息都将失败。就像调用Handler.sendMessage(Message)将返回false。
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式