亚洲免费人人妻人人,cao78在线视频,福建一级毛片,91精品视频免费观看,高清另类图片操逼,日本特黄特色大片免费看,超碰欧美人人澡曰曰澡夜夜泛

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

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

   

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

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

    1、 Looper.prepare()方法

    為當(dāng)前線程綁定looper,

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

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

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

    4、Looper.loop()

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

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

new Thread(){	    @Override	    public void run() {		Message msg = Message.obtain();		Looper.prepare();//若沒有調(diào)用此方法則拋出異常 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)建前調(diào)用Looper.prepare()方法在創(chuàng)建后調(diào)用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");        }		// 為當(dāng)前線程綁定一個looper對象,以sThreadLocal為key        sThreadLocal.set(new Looper());    }
即:調(diào)用Looper.prepare方法時為當(dāng)前線程綁定了一個Looper對象,所以Looper.prepare方法只能調(diào)用一次,即一個線程只能有一個Looper對象

    再看看Looper的構(gòu)造方法:

   

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

    先讓我們看看Handler的構(gòu)造方法:

public Handler() {	//獲得當(dāng)前線程的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方法:即獲取調(diào)用Looper.prepare方法時保存在sThreadLoad的Looper對象,所以Looper.prepare方法要在new Handler方法前調(diào)用

   

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

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

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

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

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

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

   

final boolean enqueueMessage(Message msg, long when) {                   msg.when = when; // 將執(zhí)行時間設(shè)置給msg.when            Message p = mMessages;  // 定義變量p = mMessage  ,mMessage初終指向?qū)α械牡谝粋Message 對象            if (p == null || when == 0 || when< p.when) {				// 當(dāng)隊列中為空的時候,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ā)送成功這時候該調(diào)用Looper.loop方法:即完成了從MessageQueue中取出需要執(zhí)行的Message,并執(zhí)行我們重寫的handlMessage方法

   

public static final void loop() {	//獲得當(dāng)前線程的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 對應(yīng)的handler中的dispatchMessage方法,即,執(zhí)行我們重寫的handleMessage方法             msg.target.dispatchMessage(msg);            }        }    }

最新文章