Android消息机制

在我们的Android开发中,我们都知道不能在主线程中做网络操作、耗时操作等。所以我们都会另开线程去执行这些操作,但是当操作结束之后我们又必须在主线程中去修改UI。而此时我们通常使用Handler来解决。

         在我们使用Handler的时候就涉及了Android的消息机制。我们一起来分析一下Android的消息机制。

         Android的消息机制由MessageQueue、Looper、Handler三者构成。

         MessageQueue:消息队列,用来保存handler发送的消息;其使用单链表实现。MessageQueue只包含两个主要的操作即enqueueMessage和next,分别用来插入和取出一条消息并从队列中移除。MessageQueue只负责保存消息,并不处理消息。

我们在MessageQueue的源码中可以看到next()方法有如下的代码:

Message next() {
    // Return here ifthe message loop has already quit and been disposed.
    // This can happen if the applicationtries to restart a looper after quit
    // which is not supported.
   
final long ptr = mPtr;
    if (ptr == 0) {
        return null;
    }

    int pendingIdleHandlerCount= -1; // -1 only during first iteration
   
int nextPollTimeoutMillis= 0;
    for (;;) {

        …
    }
}

从中我们可以看出,next()方法中有一个死循环,如果消息队列中没有消息,那么next()方法会一直阻塞,直到有消息过来。

 

         Looper:在主线程中使用Handler时我们一般不会涉及到Looper对象。因为在主线程中系统会默认为我们创建一个Looper对象。而在子线程中如果我们直接使用Handler会出现Can’t create handler inside thread that has not calledLooper.prepare();之所以出现这个异常是因为Handler的消息是由Looper处理的,但是我们并没有创建Loope对象。在子线程中使用Looper.prepare()即可创建Looper对象。在Looper的源码中我们通过私有的构造函数

private Looper(boolean quitAllowed) {
    mQueue = new MessageQueue(quitAllowed);
    mThread = Thread.currentThread();
}
我们可以看出Looper会创建一个MessageQueue对象,在上面我们已经知道了MessageQueue不会处理消息,而是由Looper对象处理的。在Looper.loop()方法的源码中 
/**
 * Run the message queue in this thread. Be sure to call
 * {@link #quit()} to end the loop.
 */
public static void loop() {
    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;

    // 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()方法会不断的调用MessageQueue的next()方法来查看是否有新消息。
          Handler:在Handlerde 源码中我们发现我们通过Handler对象的post和send的一系列发送消息的方法最后都会通过send方法来实现。而send一系列的方法最终都会进入如下方法:
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
    MessageQueue queue = mQueue;
    if (queue == null) {
        RuntimeException e = new RuntimeException(
                this + " sendMessageAtTime() called with no mQueue");
        Log.w("Looper", e.getMessage(), e);
        return false;
    }
    return enqueueMessage(queue, msg, uptimeMillis);
}
我们能够看出send方法其实是往消息队列中插入一条消息,而Looper对象又会通过loop()方法来调用MessageQueue对象的next()方法去获取消息,最后交给Handler的dispatchMessage方法处理。
这样Handler、MessageQueue和Looper就连同工作了。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值