Android的Handler消息机制的理解

本文详细解析了Android中Handler机制的工作原理,包括Handler、Looper、MessageQueue的角色与交互过程,以及消息如何在子线程与主线程间传递,实现UI更新。

理解Handler机制前需要了解一下什么是Handler?作用是什么?Handler就是用来处理子线更新UI问题的;接收子线程发送来的数据, 然后更新到主线程。

了解Handler消息机制,就需要了解它的几个重要参与者。

Handler :      消息机制中的发起者。使用Handler,会先在声明时初始化Handler实例。在Handler构造中,会拿到Looper的实例,通过looper的实例初始化消息队列。

mLooper = Looper.myLooper();
if (mLooper == null) {
    throw new RuntimeException(
        "Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;

这样就保证了handler的实例与我们Looper实例中MessageQueue关联上了。当我们调用发消息的方法时: sendMessage();经过跳转回到sendMessageAtTime()方法。在这个方法内部,调用了MessageQueue的enqueueMessage方法。消息就由Handler转到保存到了消息队列中去了。之前在讲述Looper时,Looper会调用prepare()和loop()方法,在当前执行的线程中保存一个Looper实例,这个实例会保存一个MessageQueue对象,然后当前线程进入一个无限循环中去,不断从MessageQueue中读取Handler发来的消息,回调创建这个消息的handler中的dispathMessage方法。在dispathMessage方法,调用了handleMessage方法。然后我们创建handler的时候都是复写handleMessage方法,然后根据msg.what进行消息处理了。

Looper:消息机制中的发动机。无限循环消息队列。主要两个方法,prepare()和looper()方法。首先在Looper的构造中,创建了一个MessageQueue(消息队列)。并且将当前运行线程赋值给所创建的线程。

prepare()方法: Looper的实例放入了ThreadLocal对象中,并且判断了ThreadLocal对象是否为null,否则抛出异常。这也就说明了Looper.prepare()方法不能被调用两次,同时也保证了一个线程中只有一个Looper实例;

looper方法:从looper实例中的拿到一个mQueue(消息队列):

final Looper me = myLooper();
if (me == null) {
    throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;

然后进入无线循环中。(就是在一个死循环中,根据消息队列的消息是否为空来判断,只有堆列中存在消息时,才开始执行下一步,否则阻塞);当拿到消息后,把消息交给msg的target的dispatchMessage方法去处理:msg.target.dispatchMessage(msg);然后释放消息资源。loopr()方法结束。

Mssage:消息对象,携带需要传递的数据。

MessageQueue: 一个消息队列,保存发出的消息,并且是阻塞队列,只有堆列中存在消息时,才开始执行下一步,否则阻塞。

 

最后总结:

 1、首先创建并初始化Handler实例,在Handler的构造方法,会首先得到当前线程中保存的Looper实例,从Looper中获取MessageQueue,进而与Looper实例中的MessageQueue想关联。

 2、而获得Looper实例时,在Looper.prepare()方法中会在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue的对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。

3、然后,Looper.loop()会让当前线程进入一个无限循环,不端从MessageQueue的实例中读取消息,然后回调msg.target.dispatchMessage(msg)方法。

for (;;) {
    Message msg = queue.next(); // might block
    if (msg == null) {
        // No message indicates that the message queue is quitting.
        return;
    }
    ..........
 }

4、当调用Handler的sendMessage方法,最后会跳转到enqueueMessage方法中,会给msg的target赋值为handler自身,msg.target = this;,然后加入MessageQueue中。这个this就是当前Handler本身。

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    msg.target = this;
    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    return queue.enqueueMessage(msg, uptimeMillis);
}

5、最后,在构造Handler实例时重写的handleMessage方法中,也就是msg.target.dispatchMessage(msg)最终调用的方法,就可以拿到发出的消息了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值