Handler消息機制源碼分析 -電腦資料

電腦資料 時間:2019-01-01 我要投稿
【m.clearvueentertainment.com - 電腦資料】

   

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

    先來個Handler執(zhí)行過程的總結

    1、 Looper.prepare()方法

    為當前線程綁定looper,

    在looper構造方法中創(chuàng)建一個messageQueue

    2、 創(chuàng)建handler 重并寫handleMessage方法

    3、 使用handler發(fā)送消息,最終消息都會發(fā)送至messageQueue對象中,在messageQueue當中,所有的message按應該執(zhí)行的時間的先后順序,從小到大排列

    4、Looper.loop()

    在此方法中,開啟死循環(huán),不斷的從messageQueue中取出應該執(zhí)行的message,并執(zhí)行message 對應的handler中的dispatchMessage方法,即,執(zhí)行我們重寫的handleMessage方法

    參照以上分析在子線程中創(chuàng)建Handler對象:

new Thread(){	    @Override	    public void run() {		Message msg = Message.obtain();		Looper.prepare();//若沒有調用此方法則拋出異常 Can't create handler inside thread that has not called Looper.prepare()		Handler handler2 = new Handler(){		    public void handleMessage(Message msg) {			Toast.makeText(MainActivity.this, "收到子線程message消息", 0).show();		    };		};		handler2.sendMessage(msg);		Looper.loop();	    }	}.start();
對比在主線程中創(chuàng)建Handler實例對象我們發(fā)現(xiàn),在子線程中創(chuàng)建Handler對象需要在創(chuàng)建前調用Looper.prepare()方法在創(chuàng)建后調用Looper.loop方法,那究竟這兩個方法是做什么的呢?

    先看看系統(tǒng)的Looper.prepare方法:

   

public static final void prepare() {        if (sThreadLocal.get() != null) {            throw new RuntimeException("Only one Looper may be created per thread");        }		// 為當前線程綁定一個looper對象,以sThreadLocal為key        sThreadLocal.set(new Looper());    }
即:調用Looper.prepare方法時為當前線程綁定了一個Looper對象,所以Looper.prepare方法只能調用一次,即一個線程只能有一個Looper對象

    再看看Looper的構造方法:

   

private Looper() {        mQueue = new MessageQueue();    }
因為一個線程只能有一個Looper對象,所以一個線程也只能有一個MessageQueue對象

    先讓我們看看Handler的構造方法:

public Handler() {	//獲得當前線程的looper對象        mLooper = Looper.myLooper();        if (mLooper == null) {            throw new RuntimeException(                "Can't create handler inside thread that has not called Looper.prepare()");        }		// 獲得looper中MessageQueue的引用        mQueue = mLooper.mQueue;    }

    再看看系統(tǒng)的Looper.myLooper方法:即獲取調用Looper.prepare方法時保存在sThreadLoad的Looper對象,所以Looper.prepare方法要在new Handler方法前調用

   

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

    即:當創(chuàng)建Handler時會先調用Looper.myLooper()方法獲取當前線程的Looper對象,如果Looper==null,則拋出異常

    通過以上兩個方法,當前線程的唯一Looper對象和MessageQueue對象都已創(chuàng)建,接下來該sendMessage了

    查看系統(tǒng)源碼可知:sendEmptyMessage等,發(fā)送信息的方法,最終都是調用了SendMessageAtTime(msg,when);

    而SendMessageAtTime(msg,when);方法最終的目的就是為了queue.enqueueMessage(msg, uptimeMillis);,其中msg為發(fā)送的Message對象,uptimeMillis為SystemClock.uptimeMillis() + when

    查看系統(tǒng)的enqueueMessage方法,該方法最終實現(xiàn)在messageQueue當中,所有的message按執(zhí)行的先后順序,從小到大排列

   

final boolean enqueueMessage(Message msg, long when) {                   msg.when = when; // 將執(zhí)行時間設置給msg.when            Message p = mMessages;  // 定義變量p = mMessage  ,mMessage初終指向對列的第一個Message 對象            if (p == null || when == 0 || when< p.when) {				// 當隊列中為空的時候,mMessage = msg                msg.next = p;                mMessages = msg;                this.notify();            } else {				// 否則將要進入隊列的msg的執(zhí)行時間和隊列中的message的執(zhí)行時間進行比較,				// 最終會使messageQueue中的所有的message按時間為順序從小到大排列				// 即按執(zhí)行的先后順序排列                Message prev = null;                while (p != null && p.when<= when) {                    prev = p;                    p = p.next;                }                msg.next = prev.next;                prev.next = msg;                this.notify();            }        }

    消息發(fā)送成功這時候該調用Looper.loop方法:即完成了從MessageQueue中取出需要執(zhí)行的Message,并執(zhí)行我們重寫的handlMessage方法

   

public static final void loop() {	//獲得當前線程的looper對象及messageQueue對象        Looper me = myLooper();        MessageQueue queue = me.mQueue;	//開啟while(true)循環(huán)        while (true) {	    //從消息隊列中取出一個message,如果message執(zhí)行時間不到,那就wait等一會            Message msg = queue.next(); // might block	    //執(zhí)行message 對應的handler中的dispatchMessage方法,即,執(zhí)行我們重寫的handleMessage方法             msg.target.dispatchMessage(msg);            }        }    }

最新文章