Android的消息机制学习(一)Looper,Handler,MessageQueue

Message,Handler是在Android中最常用的,更新UI点手段。与其他图形界面的原理类似,Android系统中UI也是靠消息驱动来工作的,具体有以下一些概念。
消息发送者:发生消息到队列
消息队列:存储消息的队列
消息循环:不断的循环取出消息,发给处理者
消息处理者:处理消息
他们的关系可以画成下图的样子:



消息机制原理图



消息循环Looper

Android消息循环由Looper类来实现。使用Looper要经过以下两个方法。
Looper.prepare();
Looper.loop();
在Activity主线程中查看就有Looper的初始化,查看ActivityThread类的main方法中,有下列代码



查看prepareMainLooper()方法第一句就调用了prepare方法。归根结底Looper的调用顺序先要调用prepare方法,然后再调用loop()方法。


1.Looper.prepare()
那我们先查看Looper的prepare方法
// sThreadLocal.get() will return null unless you've called prepare().
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

private static void prepare(boolean quitAllowed) {
    // 保证一个线程Looper只能调用一次
    // ThreadLocal并不是一个Thread,而是Thread的局部变量,
    // 也许把它命名为ThreadLocalVariable更容易让人理解一些。
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    sThreadLocal.set(new Looper(quitAllowed));
}
该方法很简单就是创建了一个Looper对象存入sThreadLocal中。
注意:ThreadLocal调用set存储,调用get获取。普通对象当在不同线程中获取时候是同一个对象,数据相同。然而ThreadLocal不同线程调用这个get,set获取到的数据是不同的,它是线程相关的局部变量。
综上一个线程只能存储一个Looper对象。

查看下Looper的构造函数。
private Looper(boolean quitAllowed) {
    mQueue = new MessageQueue(quitAllowed);
    mThread = Thread.currentThread();
}
构造函数主要就是创建了一个MessageQueue。
用图概括下

Looper.prepare()工作流程

prepare方法主要就是创建了Looper对象存在当前线程,同时Looper内创建了一个MessageQueue。
1.Looper.loop()
先看loop的源码
public static void loop() {
    //取出当前线程相关的looper对象
    final Looper me = myLooper();
    if (me == null) {
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }

    //获取当前线程Looper对象内的MessageQueue(消息队列)
    final MessageQueue queue = me.mQueue;

    // Make sure the identity of this thread is that of the local process,
    // and keep track of what that identity token actually is.
    Binder.clearCallingIdentity();
    final long ident = Binder.clearCallingIdentity();

    for (;;) {
        Message msg = queue.next(); // might block 可能阻塞
        if (msg == null) {
            // No message indicates that the message queue is quitting.
            //没有消息表明消息队列退出
            return;
        }

        // This must be in a local variable, in case a UI event sets the logger
        Printer logging = me.mLogging;
        if (logging != null) {
            logging.println(">>>>> Dispatching to " + msg.target + " " +
                    msg.callback + ": " + msg.what);
        }
        //处理消息
        msg.target.dispatchMessage(msg);

        if (logging != null) {
            logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
        }

        // Make sure that during the course of dispatching the
        // identity of the thread wasn't corrupted.
        final long newIdent = Binder.clearCallingIdentity();
        if (ident != newIdent) {
            Log.wtf(TAG, "Thread identity changed from 0x"
                    + Long.toHexString(ident) + " to 0x"
                    + Long.toHexString(newIdent) + " while dispatching to "
                    + msg.target.getClass().getName() + " "
                    + msg.callback + " what=" + msg.what);
        }

        msg.recycleUnchecked();
    }
}
查看loop方法,主要就是开启了消息循环,内部就是一个for循环一直获取一个个的Message调用msg.target.dispatchMessage处理。
1.获取调用线程的Looper对象,获取Looper对象内的MessageQueue
2.循环调用MessageQueue的next方法获取下一个元素
3.最终调用target的dispatchMessage方法处理Message。
4.继续步骤2

Looper.loop()工作流程

消息队列MessageQueue

MessageQueue主要提供了向队列插入Message的方法,获取下一个Message的方法。其类内部的成员变量
final MessageQueue mQueue;
为一个链表,存储所有的Message看下Message链表的结构应该是下图的样子

整个队列按照when变量从小到大排序,next变量指向下一个节点,其中的callback与target是消息最终的处理者。
上一节主要讲了loop方法内有个for循环,for内部会一直获取下一条Message。这里就看以下这个next方法。
MessageQueue的next方法是获取队列中的下一条Message
Message 
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值