handler底层是如何将消息从子线程发送到主线程

来源:互联网 发布:用友u8数据库修复工具 编辑:程序博客网 时间:2024/06/10 12:52

这个问题的实质是handler机制+引用的传递.
理解handler机制有很多方法,我推荐的方法是从四个关键类Handler、Message、MessageQueue、Looper的方法入手来弄清消息传递这一整条线的逻辑:
这条线的走向是:(相关对外提供的方法可以用eclipse或者source insight来查看.)
1产生消息对象
2-->消息相关属性(what,obj,target,callback等)的附加
3-->消息加入到消息队列
4-->Looper对消息队列的循环取出
5-->分发(也就是执行消息内用户定义的处理逻辑)
6-->回收消息对象

从子线程发送到主线程的消息分两种,一种是普通的handler.sendMessage(msg)或定义延时send,另一种是handler.post(Runnable r)或定时或延时post.不管是哪一种,都用到了handler,那么这个handler就会赋值给msg.target.
常见的情况下,handler在主线程中new出来,然后在子线程中拿到它的引用,发送了消息,系统把消息加入到消息队列中,然后就会有一个Looper来从消息队列中取消息.

这个流程中要注意几个对应关系:
一个线程中最多只能有一个Looper,也可以没有.主线程中初始化时已建立Looper.子线程默认没有,如果使用,需要手动创建.
一个Looper对应一个消息队列.也就是说,有几个Looper,就有几个消息队列,

那么一个Message发送时,怎么知道它要加入到哪个消息队列中去?
一个handler持有一个消息队列的引用和它构造时所属线程的Looper的引用.
也就是说,一个handler必定有它对应的消息队列和Looper,
一个线程至多能有一个Looper,也就至多能有一个消息队列.
一个线程中可以有多个handler.

在主线程中new了handler对象后,这个handler对象自动和主线程自动生成的Looper以及消息队列关联上了.
子线程中拿到主线程中handler的引用,发送消息后,消息对象就会发送到target属性对应的那个handler对应的消息队列中去,由对应的Looper来取出处理.
而消息发送到主线程handler,那么也就是发送到主线程的消息队列,用主线程中的Looper轮询.

Looper的loop方法在它关联的线程中执行(比如主线程),但这是一个阻塞式方法,由消息触发后调用循环内部后面部分的handler.dispatchMessage(),实质是调用handler.handleMessage()或runnable.run()执行自定义的逻辑.

0 0
原创粉丝点击