Android的消息处理机制源码分析

好久没写博客了,最近看了看关于Handler,Looper和MessageQueue的源码,感觉对他们的了解又多了几分,在这整理一下思路,如果有不对的地方,欢迎指正。
先从Looper说起,以下官方文档:
Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped. Most interaction with a message loop is through the Handler class. This is a typical example of the implementation of a Looper thread, using the separation of prepare() and loop() to create an initial Handler to communicate with the Looper.

class LooperThread extends Thread {
      public Handler mHandler;

      public void run() {
          Looper.prepare();

          mHandler = new Handler() {
              public void handleMessage(Message msg) {
                  // process incoming messages here
              }
          };

          Looper.loop();
      }   }
官方文档的大体意思翻译一下(本人英语非常的渣,英语好的就略过我的翻译吧):Looper被用来为一个线程运行一个消息循环,默认的线程没有消息循环与他们绑定;创建一个Looper对象,在线程中调用prepare()方法来运行一个Looper,然后loop()是他循环处理消息,知道loop停止,大多数与消息队列的交互通过Handler类。
这里我们大概明白了Looper的作用,就是不断取出消息,处理消息。

其中里面比较重要的方法有prepare()和loop(),下面来看看他们的源码是怎样的:

public final class Looper {
    private static final String TAG = "Looper";

    // sThreadLocal.get() will return null unless you've called prepare().
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    private static Looper sMainLooper;  // guarded by Looper.class

    final MessageQueue mQueue;
    final Thread mThread;

    private Printer mLogging;

     /** Initialize the current thread as a looper.
      * This gives you a chance to create handlers that then reference
      * this looper, before actually starting the loop. Be sure to call
      * {@link #loop()} after calling this method, and end it by calling
      * {@link #quit()}.
      */
    public static void prepare() {
        prepare(true);
    }

    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

    /**
     * Initialize the current thread as a looper, marking it as an
     * application's main looper. The main looper for your application
     * is created by the Android environment, so you should never need
     * to call this function yourself.  See also: {@link #prepare()}
     */
    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }

    /**
     * Returns the application's main looper, which lives in the main thread of the application.
     */
    public static Looper getMainLooper() {
        synchronized (Looper.class) {
            return sMainLooper;
        }
    }


    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中的消息队列
        final MessageQueue queue = me.mQueue;
    //这两句没看太懂,不过没影响对大体意思的理解
        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);
            }
    //调用消息的target的dispatchMessage(),target其实就是一个Handler对象,下文会讲到。
            msg.target.dispatchMessage(msg);

            if (logging != null) {
                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
            }
    //这个没看太懂,还不影响
            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();
        }
    }
    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }

   ........
}

可以看到Looper的prepare()方法主要是新建一个Looper及其他准备工作。
而loop()方法的大体流程实在for循环中,首先获得本线程的Looper,然后获得Looper的消息队列,然后不断地取出消息,处理消息,回收消息。我们可以看到在Looper的loop()方法里面是通过MessageQueue这个类的next取出消息的,下边就来看看MessageQueue的next方法的源码。

Message next() {
        //这个mPtr其实是一个消息队列的指针,他是在native层实现的
        final long ptr = mPtr;
        if (ptr == 0) {
            return null;
        }

        int pendingIdleHandlerCount = -1; // -1 only during first iteration
        int nextPollTimeoutMillis = 0;
        for (;;) {
            if (nextPollTimeoutMillis != 0) {
                Binder.flushPendingCommands();
            }

            nativePollOnce(ptr, nextPollTimeoutMillis);

            synchronized (this) {
                // Try to retrieve the next message.  Return if found.
                final long now = SystemClock.uptimeMillis();
                Message prevMsg = null;
                Message msg = mMessages;
                if (msg != null && msg.target == null) {
                    // Stalled by a barrier.  Find the next asynchronous message in the queue.
                    do {
                        prevMsg = msg;
                        msg = msg.next;
                    } while (msg != null && !msg.isAsynchronous());
                }
                if (msg != null) {
                    if (now < msg.when) {
                        // Next message is not ready.  Set a timeout to wake up when it is ready.
                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
                        // Got a message.
                        mBlocked = false;
                        if (prevMsg != null) {
                            prevMsg.next = msg.next;
                        } else {
                            mMessages = msg.next;
                        }
                        msg.next = null;
                        if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                        msg.markInUse();
                        return msg;
                    }
                } else {
                    // No more messages.
                    nextPollTimeoutMillis = -1;
                }

                // Process the quit message now that all pending messages have been handled.
                if (mQuitting) {
                    dispose();
                    return null;
                }

                // If first time idle, then get the number of idlers to run.
                // Idle handles only run if the queue is empty or if the first message
                // in the queue (possibly a barrier) is due to be handled in the future.
                if (pendingIdleHandlerCount < 0
                        && (mMessages == null || now < mMessages.when)) {
                    pendingIdleHandlerCount = mIdleHandlers.size();
                }
                if (pendingIdleHandlerCount <= 0) {
                    // No idle handlers to run.  Loop and wait some more.
                    mBlocked = true;
                    continue;
                }

                if (mPendingIdleHandlers == null) {
                    mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
                }
                mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
            }

            // Run the idle handlers.
            // We only ever reach this code block during the first iteration.
            for (int i = 0; i < pendingIdleHandlerCount; i++) {
                final IdleHandler idler = mPendingIdleHandlers[i];
                mPendingIdleHandlers[i] = null; // release the reference to the handler

                boolean keep = false;
                try {
                    keep = idler.queueIdle();
                } catch (Throwable t) {
                    Log.wtf(TAG, "IdleHandler threw exception", t);
                }

                if (!keep) {
                    synchronized (this) {
                        mIdleHandlers.remove(idler);
                    }
                }
            }

            // Reset the idle handler count to 0 so we do not run them again.
            pendingIdleHandlerCount = 0;

            // While calling an idle handler, a new message could have been delivered
            // so go back and look again for a pending message without waiting.
            nextPollTimeoutMillis = 0;
        }
    }

其实这个方法就是消息队列从队列中取出来消息。
下面是MessageQueue的文档:
Low-level class holding the list of messages to be dispatched by a Looper. Messages are not added directly to a MessageQueue, but rather through Handler objects associated with the Looper.
You can retrieve the MessageQueue for the current thread with Looper.myQueue().
大体意思是这个类控制着Looper里面被发送的消息列表;消息不能直接加在MessageQueue上,而是通过Handler对象与Looper共同完成的;你可以取回当前线程的消息队列用Looper.myQueue()。
所以它的作用就是管理消息队列。
上面说到Looper管理和处理消息,管理消息交给了MessageQueue来做,而处理消息的那一行代码是: msg.target.dispatchMessage(msg);,而target是Handler的对象,也就是处理消息交给了Handler的dispatchMessage来实现的,下面看看Handler的dispatchMessage的源码:

public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

这段代码很容易看懂,就是先检查消息中的callback是否为空,如果不为空就调用handleCallback(msg),如果为空,就看看Hander的mCallback字段是否为空,mCallback是一个Callback接口对象,接口的定义如下:

public interface Callback {
        public boolean handleMessage(Message msg);
    }

其实就是handlerMessage()函数,如果mCallback字段为空,则调用接口的handlerMessage方法,为真的时候返回,如果mCallback字段bu为空或者上面说的返回假,则调用handleMessage(msg);方法,下面是handleMessage(msg)的源码:

 public void handleMessage(Message msg) {
    }

其实他是个空方法,所以我们以前定义自己的Handler的时候都会重写这个方法,在这个方法里自己定义处理消息的代码。这下我们看一下Handler的官方文档:
A Handler allows you to send and process Message and Runnable objects associated with a thread’s MessageQueue. Each Handler instance is associated with a single thread and that thread’s message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it – from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.
There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.
Scheduling messages is accomplished with the post(Runnable), postAtTime(Runnable, long), postDelayed(Runnable, long), sendEmptyMessage(int), sendMessage(Message), sendMessageAtTime(Message, long), and sendMessageDelayed(Message, long) methods. The post versions allow you to enqueue Runnable objects to be called by the message queue when they are received; the sendMessage versions allow you to enqueue a Message object containing a bundle of data that will be processed by the Handler’s handleMessage(Message) method (requiring that you implement a subclass of Handler).
When posting or sending to a Handler, you can either allow the item to be processed as soon as the message queue is ready to do so, or specify a delay before it gets processed or absolute time for it to be processed. The latter two allow you to implement timeouts, ticks, and other timing-based behavior.
When a process is created for your application, its main thread is dedicated to running a message queue that takes care of managing the top-level application objects (activities, broadcast receivers, etc) and any windows they create. You can create your own threads, and communicate back with the main application thread through a Handler. This is done by calling the same post or sendMessage methods as before, but from your new thread. The given Runnable or Message will then be scheduled in the Handler’s message queue and processed when appropriate.
非常的长,我说一下大体意思:
一个Handler允许你发送和处理消息和Runnable对象与一个线程的MessageQueue相关联;每一个Handler实例联合一个单独的线程和消息队列;当创建一个新的Handler时,他被绑定在创建他的线程/线程的消息队列,从那时起,它将被传送消息和Runnable实例向消息队列,并执行他们的消息队列。
用Handler的两种情景:一是在未来的某个时间点去执行一个消息和Runnable实例,二是在你的线程中排队一个动作去执行。
调度消息可以用 post(Runnable), postAtTime(Runnable, long), postDelayed(Runnable, long), sendEmptyMessage(int), sendMessage(Message), sendMessageAtTime(Message, long), and sendMessageDelayed(Message, long)方法来实现,发布方法里面,你可以排队一个Runnable对象被调用在消息队列里被接收,sendMessage方法里面可以入队一个消息对象,而且将会在Handler的 handleMessage(Message) 里被处理…
从这我们可以知道线程是用post和sendMessage来发Runnable对象和消息的,下面看看这两个方法的源码:

public final boolean post(Runnable r)
    {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }
    public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }

其实这两个方法都是调用了sendMessageDelayed方法,只不过post方法在这之前调用了getPostMessage方法:

private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }

我们可以看到,其实这个方法就是把Runnable封装到了一个Message里,然后再调用sendMessageDelayed方法,接着看sendMessageDelayed方法的实现:

public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }

这个方法是吧延迟的时间加上了SystemClock.uptimeMillis() ,SystemClock.uptimeMillis() 方法返回的是从boot到现在的时间,就是从开机到现在的时间,然后再调用sendMessageAtTime方法:

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);
    }

这个方法又调用了enqueueMessage(queue, msg, uptimeMillis):

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

这时我们终于看到了,其实最后是调用了MessageQueue的enqueueMessage方法,这个enqueueMessage方法其实就是根据两个参数把消息按时间放到消息队列里面。
现在我们知道了,其实Looper的主要作用就是一个死循环,不断地取出消息,处理消息,取出消息是调用的MessageQueue方法next,而处理消息是调用的Handler的handleMessage方法,这个方法是个空方法,需要我们重写,而向消息队列里面添加时通过Handler的post和sendMessage等一系列方法,而这些方法其实是调用了MessageQueue的enqueueMessage方法实现的消息的入队操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值