Android消息机制浅析

来源:互联网 发布:股市大数据 编辑:程序博客网 时间:2024/05/21 18:43
private Handler handler=new Handler(){    public void handleMessage(Message msg){        //...    }}new Thread(new Runnable(){    public void run(){        //...        //...        //...        handler.sendMessage(msg);    }}).start();

上述代码是子线程更新UI界面常用的步骤,现在就来看看从new Handler开始,到handler.sendMessage之后都经历了哪些过程。

new Handler():

public Handler(Callback callback, boolean async) {        if (FIND_POTENTIAL_LEAKS) {            final Class<? extends Handler> klass = getClass();            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&                    (klass.getModifiers() & Modifier.STATIC) == 0) {                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +                    klass.getCanonicalName());            }        }        //获得当前线程的Looper             mLooper = Looper.myLooper();        if (mLooper == null) {            throw new RuntimeException(            //这句话可以看出,在线程中创建handler的时候必须先调用Looper.prepare()                "Can't create handler inside thread that has not called Looper.prepare()");        }        //从looper中获取消息队列        mQueue = mLooper.mQueue;        mCallback = callback;        mAsynchronous = async;    }

来看上述代码我的三处注释

//获得当前线程的Looper     mLooper = Looper.myLooper();

来看一下myLooper的源码:

/*** Return the Looper object associated with the current thread.  Returns* null if the calling thread is not associated with a Looper.*/    public static @Nullable Looper myLooper() {        return sThreadLocal.get();    }

解释下ThreadLocal,它不是一个线程,而是一个线程内部数据存储类,当某些数据是以线程为作用域并且不同线程具有不同副本的时候就可以用到这个。
Android中通过ThreadLocal将Looper保存到各自的线程中,于是,每个线程就有了各自的Looper中的MessageQueue。

//从looper中获取消息队列mQueue = mLooper.mQueue;

拿到当前线程的Looper中就从looper中拿到MessageQueue。
那么这个mQueue是什么时候被创建的呢?进到Looper源码中:

    public static void prepare() {        prepare(true);    }    //这个是主线程Looper的创建,平时用的handler都是创建在主线程中的    public static void prepareMainLooper() {        prepare(false);        synchronized (Looper.class) {            if (sMainLooper != null) {                throw new IllegalStateException("The main Looper has already been prepared.");            }            sMainLooper = myLooper();        }    }    private static void prepare(boolean quitAllowed) {        if (sThreadLocal.get() != null) {        //注意一下,每个线程只能有一个Looper,也就只有一个MessageQueue        throw new RuntimeException("Only one Looper may be created per thread");        }        sThreadLocal.set(new Looper(quitAllowed));    }    //Looper的构造函数    private Looper(boolean quitAllowed) {        mQueue = new MessageQueue(quitAllowed);        mThread = Thread.currentThread();    }

从源码可以看到,mQueue是在实例化Looper的时候被创建的,Looper的构造函数又是在prepare的时候调用的。

sendMessage(msg):

一路追踪,各种sendMessage最终都会调用以下函数:

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)看源码,看书上解释的是MessageQueue的插入操作,虽然是叫MessageQueue,但它的实现不是队列,而是一个单链表。

到这里就完成了handler.sendMessage。

接下来就是接受和处理Message了。

Looper捕获Message:

public static void loop() {    //前面的省略,直接看重点...    //无线循环,唯一退出条件是queue返回null   for (;;) {    //从MessageQueue中获取Message     Message msg = queue.next();      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 + " " +         sg.callback + ": " + msg.what);     }     //这个target就是Handler,这里调用方法让Handler处理消息     msg.target.dispatchMessage(msg);   }}

在主线程当中,这个loop()是会在ActivityThread中被调用:

public static void main(String[] args) {          ....          Looper.prepareMainLooper();          ActivityThread thread = new ActivityThread();          thread.attach(false);          if (sMainThreadHandler == null) {              sMainThreadHandler = thread.getHandler();          }          AsyncTask.init();          Looper.loop();          throw new RuntimeException("Main thread loop unexpectedly exited");      }  

Handler处理Message:

 public void dispatchMessage(Message msg) {         //首先检查Message的callback是否为null        if (msg.callback != null) {            handleCallback(msg);        } else {            //其次检查Handler的callback是否为null            if (mCallback != null) {                if (mCallback.handleMessage(msg)) {                    return;                }            }            //如果前两者都为null,执行handleMessage(),由handler子类实现            handleMessage(msg);        }    }     /**     * Handler子类必须实现的方法     * Subclasses must implement this to receive messages.     */    public void handleMessage(Message msg) {    }

有个地方没注意:

Message next() {        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.                    //这里注意,没有Message是不返回null的!                    nextPollTimeoutMillis = -1;                }                // 如果到了这里还没有返回,那说明没有Message了,检查下MessageQueue是否要退出,如果是,返回null,同时结束Looper.looper()的无限for循环                if (mQuitting) {                    dispose();                    return null;                }     }
0 0
原创粉丝点击