91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Handler原理淺析

發布時間:2020-06-26 00:06:02 來源:網絡 閱讀:464 作者:focus_000 欄目:移動開發

    理解Handler的原理首先要搞清楚什么是Looper,在我的上一篇博文中對此有專門的介紹。Looper的作用是開啟一個消息循環,從MessageQueue(Message隊列,是Looper的成員變量)中循環取出消息處理。一個線程要使用Handler來處理來自其它線程的消息,這個線程必須有且僅有一個Looper對象與之綁定,也可以說一個Looper對象是是與一個線程一一對應的。

    Hander有一個Looper類型的成員,在Handler的構造函數(new Handler()或者new Handler(CallBack))中會實例化這個Handler的Looper成員,Handler()構造函數的源碼如下:

public Handler() {

        //獲得當前線程在 ThreadLocal 中所對應的 Looper

        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 = null;

}

 在Handler構造函數中實例化的Looper不是通過new關鍵字來實例化的,而是從Looper.myLooper()這個靜態方法中取得的。而Looper.myLooper()又是從哪來取得的Looper對象呢?這就涉及到另外一個類ThreadLocal。Looper有一個靜態變量是ThreadLocal類型的:

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); 

 這個變量就是保存每一個線程和這個線程對應的Looper。這樣設計的作用是保證每一個線程的Looper是唯一的。

每一個線程在new Handler()之前必須為這個線程創建Looper對象,使用Looper.prepare()方法創建。

Looper.prepare的源碼如下:

public static void prepare() {

        //調用此方法的線程是否在 全局變量 sThreadLocal(即Map<Thread,Looper>)中存有一組以此線程為鍵的鍵值對

        if (sThreadLocal.get() != null) {

            throw new RuntimeException("Only one Looper may be created per thread");

        }

        //如果在Map<Thread,Looper>中沒有存放當前線程對應的鍵值對當存入

        // 一個 set 操作,其實就是在 Map 中插入了一組 <Thread,Looper>值,即 <調用此方法的線程,new Looper()>

        // new Looper() 時,Looper的構造函數就會實例化一個 MessageQueue

       &nbsp;sThreadLocal.set(new Looper());

關鍵是sThreadLocal.set(new Looper());這條語句,它會把new 出來的Looper保存到ThreadLocal這個全局變量中。

有一個問題,就是為什么我們在主線程中new Handler(){...}之前不需要使用Looper.prepare()呢?因為在主線程執行之前,android虛擬機已經幫我們執行了這段代碼,因此在主線程中創建Handler對象不需要再新建Looper對象。創建了Handler之后,還要使用Looper.loop()開啟消息循環來取消息。主線程也不需要這句代碼。

總結:

Looper負責開啟消息循環,從MessageQueue中讀取Message,由Handler負責處理讀出來的Message。

Looper和它的MessageQueue與某一個線程是一一對應的。

使用Handler之前需要使用Looper.prepare()為當前線程創建Looper對象。

使用Looper.loop()開啟消息循環。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

喀喇| 民和| 张掖市| 阿克苏市| 怀仁县| 绍兴县| 阳高县| 峨边| 三亚市| 汉川市| 石嘴山市| 遂宁市| 金秀| 长岭县| 广州市| 威宁| 嫩江县| 乡城县| 盐池县| 吴堡县| 延庆县| 彩票| 孙吴县| 彰武县| 阳高县| 甘孜| 麦盖提县| 鲁甸县| 揭西县| 图们市| 镇赉县| 科尔| 嘉祥县| 秦皇岛市| 察雅县| 渝北区| 密山市| 元谋县| 乌拉特后旗| 仁布县| 文化|