Handler機制(三)----Looper源碼解析,handler----looper

來源:互聯網
上載者:User

Handler機制(三)----Looper源碼解析,handler----looper
一、Looper

Looper對象,顧名思義,直譯過來就是迴圈的意思,從MessageQueue中不斷取出message。

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.

1.Looper的成員變數:

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();private static Looper sMainLooper;  // guarded by Looper.classfinal MessageQueue mQueue;  //一個MQfinal Thread mThread;    //一個thread

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

先看看prepare方法。

Looper.prepare
public static void prepare() {        prepare(true);    }    private static void prepare(boolean quitAllowed) {        if (sThreadLocal.get() != null) {//每個線程只能有一個looper            throw new RuntimeException("Only one Looper may be created per thread");        }        //設定本線程的looper。        sThreadLocal.set(new Looper(quitAllowed));    }

  注意prepare(boolean)方法中,有一個sThreadLocal變數(ThreadLocal為每個使用該變數的線程提供獨立的變數副本,所以每一個線程都可以獨立地改變自己的副本),這個變數有點像一個雜湊表,它的key是當前的線程,也就是說,它可以儲存一些資料/引用,這些資料/引用是與當前線程是一一對應的,在這裡的作用是,它判斷一下當前線程是否有Looper這個對象,如果有,那麼就報錯了,"Only one Looper may be created per thread",一個線程只允許建立一個Looper,如果沒有,就new一個。然後它調用了Looper的構造方法。

Looper 的構造方法

在上邊調用了構造方法:Looper(quitAllowed),初始化了messageQueue並綁定當前線程。

private Looper(boolean quitAllowed) {        mQueue = new MessageQueue(quitAllowed);        mThread = Thread.currentThread();    }

此時的初始化動作已經結束了,接下來看Looper.loop():

 

public static void loop() {        final Looper me = myLooper();//返回當前的looper        if (me == null) {            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");        }        final MessageQueue queue = me.mQueue;//取得messageQueue                for (;;) {            Message msg = queue.next(); // might block            if (msg == null) {                // No message indicates that the message queue is quitting.                return;            }            。。。。            msg.target.dispatchMessage(msg);            。。。            msg.recycleUnchecked();        }    }

 

loop()方法,省去了一些不關心的部分。剩下的部分非常的清楚了,首先調用了靜態方法myLooper()擷取當前Looper對象。沒有looper則拋出異常。

public static @Nullable Looper myLooper() {        return sThreadLocal.get();    }

1. myLooper()同樣是靜態方法,它是直接從這個ThreadLocal中去擷取Looper對象,拿到當前線程的Looper後;

2. MessageQueue queue = me.mQueue;拿到與這個Looper對應的MQ,就開始無限迴圈,不斷的從訊息佇列中取出Message,當擷取到一個訊息後,它調用了Message.target.dispatchMessage()方法來對訊息進行處理。dispatchMessage這個方法在Handler中,就是處理message。

3.msg.recycleUnchecked(),當這個msg處理完了,就沒有用啦,把它回收到全域池中,注意不是銷毀。

總結

Looper的代碼看完了,我們得到了幾個資訊:

  • Looper調用靜態方法prepare()來進行初始化,一個線程只能建立一個與之對應的LooperLooper初始化的時候會建立一個MQ,並和當前線程綁定,因此,有了這樣的對應關係,一個線程對應一個Looper,一個Looper對應一個MQ。

  • Looper調用靜態方法loop()開始無限迴圈的取訊息,messageQueue調用next()方法來擷取訊息(這也是個無限迴圈)。

MessageQueue源碼解析:http://www.cnblogs.com/jycboy/p/5786682.html

 

Message源碼解析:http://www.cnblogs.com/jycboy/p/5786551.html

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.