天天看點

Android FrameWork源碼淺析之(一)--handler,looper,messagequeue1.handler的建立和初始流程。2.handler的發送消息和接收消息。

我們經常會用handler接收異步線程的資料,然後進行ui重新整理,或是其他邏輯操作。

希望通過了解相關的操作,作為framework源碼入門的階梯。

handler主要涉及framework的三個類:

Handler,Looper,MessageQueue

1.handler的建立和初始流程。

Handler的主要建立如下:

</pre>
           
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());
            }
        }

        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }
           
public interface Callback {
        public boolean handleMessage(Message msg);
    }
           
public Handler(Callback callback) {
        this(callback, false);
    }
           
一般來說,建立handler時,使用new handler(this),然後複寫handleMessage方法,從源碼的角度就可以很清楚的看到handler建立和複寫方法的流程。 在建立過程中,看一下下面這段代碼。
mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
           
我們再來看一下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
* {@link #prepare} in the thread that is to run the loop, and then
* {@link #loop} to have it process messages until the loop is stopped.      
這時候可能會有疑問,在activity使用的時候,并沒有prepare的操作啊。 這裡請先看一下looper的兩個全局變量。
</pre><pre name="code" class="java"><span style="font-size:14px;"> static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    private static Looper sMainLooper;  // guarded by Looper.class</span>
           
這裡要看一下ThreadLocal這個類。下面是百度百科的結果,具體的用法可以自行搜尋,
JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal為解決多線程程式的并發問題提供了一種新的思路。      
使用這個工具類可以很簡潔地編寫出優美的多線程程式,ThreadLocal并不是一個Thread,而是Thread的局部變量。      
通常情況下,在activity中使用handler是不需要建立looper的,因為在activity的建立過程中,      
ActivityThread.java會使用 Looper.prepareMainLooper();建立一個主線程的looper,一般handler都是      
在主線程中處理資料,就不需要初始化了。      
在looper建立的時候,會初始化一個messagequeue.      
private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }
           
MessageQueue.java
* Low-level class holding the list of messages to be dispatched by a
* {@link Looper}.  Messages are not added directly to a MessageQueue,
* but rather through {@link Handler} objects associated with the Looper.
* 
* <p>You can retrieve the MessageQueue for the current thread with
* {@link Looper#myQueue() Looper.myQueue()}.      
MessageQueue(boolean quitAllowed) {
        mQuitAllowed = quitAllowed;
        mPtr = nativeInit();
    }
           
nativeInit()的源碼在:/frameworks/base/core/jni/android_os_MessageQueue.cpp,偶對C++不熟,就不搬門弄斧了。 關于messagequeue的處理可以參考下面這篇博文:http://blog.csdn.net/kesalin/article/details/37765707

2.handler的發送消息和接收消息。

public final Message obtainMessage(int what, Object obj)
    {
        return Message.obtain(this, what, obj);
    }
           
<pre name="code" class="java">    public static Message obtain(Handler h, int what, Object obj) {
        Message m = obtain();
        m.target = h;
        m.what = what;
        m.obj = obj;

        return m;
    }
           
/**
     * Return a new Message instance from the global pool. Allows us to
     * avoid allocating new objects in many cases.
     */
    public static Message obtain() {
        synchronized (sPoolSync) {
            if (sPool != null) {
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                m.flags = 0; // clear in-use flag
                sPoolSize--;
                return m;
            }
        }
        return new Message();
    }
           
從上面的源碼可以看到message發送消息的時候,實際上是在handler下建立一個message順序連結清單。

handler又是如何取資料的呢? 在Looper loop會建立一個隊列,依次從queue中取出資料。

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

其他代碼的函數,如handler中的sendMessageAtTime等就請自行閱讀吧。~

繼續閱讀