继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Handler消息机制

繁花不似锦
关注TA
已关注
手记 337
粉丝 50
获赞 241

!通过阅读Android开发艺术探索整理

存在的原因: Android UI 控件是非线程安全的,多线程并发访问会导致控件不可控,如果用锁会阻塞,降低访问效率,另外会让UI的访问变的复杂。因此选择单线程模型操作UI

相关概念:

Handler与Message/Looper/MessageQuene的关系:

Looper.perpare实例化当前线程对应的Looper及消息队列MessageQuene

Handler.post(Runnable)与Handler.sendMessage:

线程队列与消息队列

post通过sendMessageDelay()最终将getMessage(Runnable)取得的Message对象发送到消息队列

sendMessage本质最终是通过enqueueMessage将Message对象插入到消息队列

Looper.loop开启无限循环,通过消息队列内的循环next方法,不断从MessageQunene取出Message,通过msg.target.dispathMessage分发到Handler中,此处msg.target为发送该消息的Handler对象,由handleMessage处理

退出循环:Looper.quit或Looper.quitSafity

主线程的特殊性:

Looper.perpareMainLooper实例化Looper与消息队列

使用getMainLooper处理Message

通过Looper.loop实现主线程循环

ActivityThread.H:主线程Handler,内部定义四大组件启动停止消息类型

主线程消息循环:

主线程ActivityThread通过ApplicationThread与AcitivityManagerService进程间通信。AMS完成ActiviyThread请求后回调ApplicationThread内的Binder,向ActivityThread.H发送消息,H将ApplicationThread逻辑切换到ActivityThread执行,完成主线程消息循环

消息机制流程:

Looper.perpare实例化Looper对象与MessageQuene消息队列,子线程Handler对象通过postRunnable或sendMessage方法向消息队列内插入Message,Looper.loop方法调用MessageQuene的next方法查询并取出消息队列内的Message对象,dispathMessage分发给主线程的Handler,Handler对象调用handleMessage处理。 

这里引申一个面试时遇到的问题:能否在主线程开启Looper.loop?

简单说一下我的思路.

1.Looper.loop方法采用死循环方式调用消息队列的next方法查询取出Message对象,除非取到Message对象,否则将一直阻塞

2.主线程防止anr规则是耗时任务放到子线程完成

3.主线程采用的是特殊的Looper对象,通过Looper.perpareMainLooper获取

4.猜想:若主线程可以调用Looper.loop,由于该方法为阻塞式方法,将有可能导致主线程anr;若不可以调用Looper.loop方法,那么主线程消息模型通过什么完成消息循环机制?那么这个问题的本质就是主线程如何保证loop时不产生anr?

下面提供一个知乎上的回答:https://www.zhihu.com/question/34652589,讲的还是比较详细。

我在这里简单做个针对该问题的整理

loop方法的死循环并非简单的死循环,在消息队列无消息时,会阻塞在消息队列next中的native方法里,底层是linux管道机制,此时主线程会释放CPU资源进入休眠,直到下一个消息到达,通过向pipe管道写入数据唤醒主线程工作。

真正在Activity中导致anr的是在onCreate/onStart/onResume 操作时间过长,而我们的Looper.loop方法是不会导致anr的。

原文链接:http://www.apkbus.com/blog-35555-68767.html

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP