日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

【Android】Handler 机制 ( Handler | Message | Looper | MessageQueue )

發(fā)布時間:2025/6/17 Android 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Android】Handler 机制 ( Handler | Message | Looper | MessageQueue ) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

  • I . Handler 機制簡介
  • II . Handler 機制 Handler Message Looper MessageQueue 四組件對應關系
  • III . Handler ( 消息處理者 )
  • IV . Looper ( 消息遍歷者 )
  • V . Looper 子線程
  • VI . Handler 發(fā)送 消息 種類
  • VII . Handler 機制總結





I . Handler 機制簡介



Handler 機制是 Android 中最重要的 異步通信 機制 ;



1 . Handler 機制作用 : 將需要執(zhí)行的任務分配給其它線程 ;


① 子線程更新 UI : 在子線程中更新 UI , 就是在子線程中將刷新 UI 的任務分配給了主線程 ; ( 子線程刷新 UI 會崩潰 )

② 主線程網絡操作 : 在主線程中 , 將網絡通信等耗時的操作分配給子線程 ( 該子線程需要轉成 Looper 線程 ) , 避免 UI 卡頓 ; ( 主線程訪問網絡會崩潰 )



2 . Handler 機制中涉及到的組件 :


① Handler ( 消息處理者 ) : 定義具體的代碼操作邏輯 , 處理收到消息 ( Message ) 后的具體操作 ;

② Message ( 消息 ) : 定義具體消息 , 其中可以封裝不同的變量 , 為 Handler 指定操作的類型 , 或執(zhí)行操作所需的數(shù)據 ;

③ Looper ( 消息遍歷者 ) : 消息的遍歷者 , 遍歷 MessageQueue 中的消息 , 分發(fā)給 Handler 處理 ;

④ MessageQueue ( 消息隊列 ) : 封裝在 Looper 中 , 每個 Looper 中封裝了一個 MessageQueue , 是 Looper 消息遍歷的重要組件 , 用戶不直接調用該組件 ;



3 . Handler 機制中的 封閉性 與 線程交互 :


① 線程內部相對封閉的運行系統(tǒng) : 整個 Looper 線程內部是一個封閉運行的系統(tǒng) , Looper 一直不停的再遍歷 MessageQueue , 將 消息 或 操作 取出 , 交給 Handler 執(zhí)行 ;

② 線程交互 : Handler 還有另外一個職責就是負責與外部線程的交互 , 在外部線程中調用 Handler 將消息回傳給本 Looper 線程 , 放入 MessageQueue 隊列中 ;



4 . Message ( 消息 ) 的運行路徑 ( 重點 ) : 在外部線程中 , 調用 Looper 線程的 Handler 成員 , 將 Message ( 消息 ) 發(fā)送給 Looper 線程中的 MessageQueue ( 消息隊列 ) , 然后 Looper 輪詢該 消息隊列時 , 又將該消息交給 Handler 進行處理 ;

Message -> Handler ( 發(fā)送 ) -> MessageQueue ( 存儲 ) -> Looper ( 輪詢 ) -> Handler ( 執(zhí)行 )





II . Handler 機制 Handler Message Looper MessageQueue 四組件對應關系



Handler , Message , Looper , MessageQueue 四組件對應關系 :


Handler 機制中的上述四者的對應關系 : 一個線程中只能有一個 Looper 及 Looper 中封裝的 MessageQueue , 每個 Looper 可以為多個 Handler 調度消息 , Message 消息可以有無數(shù)個 ;


Looper 是 線程本地存儲的對象 ( ThreadLocal ) , 一個線程只能存在一個 , MessageQueue ( 消息隊列 ) 定義在 Looper 內部 , 每個 Looper 中只定義了一個 MessageQueue ( 消息隊列 ) , 因此每個線程也只能有一個 MessageQueue ;


線程 與 Looper ( 消息遍歷者 ) 是一對一關系 , Looper ( 消息遍歷者 ) 與 MessageQueue ( 消息隊列 ) 是一對一的關系 , Looper ( 消息遍歷者 ) 與 Handler ( 消息處理者 ) 是一對多的關系 , Message ( 消息 ) 可以有很多 ;





III . Handler ( 消息處理者 )



1 . Handler 創(chuàng)建 : 這里注意 只能在 Looper 線程中創(chuàng)建 Handler , 普通線程不能創(chuàng)建 Handler ;


① 主線程 : 主線程中可以直接創(chuàng)建 Handler , 因為在點擊應用圖標后就會 啟動主線程 ActivityThread , 此時就已經將 Looper 實例化好了 , 因此我們在 Activity 中 , 可以任意創(chuàng)建多個 Handler , 并直接使用 ;

public final class ActivityThread {...public static void main(String[] args) {...Looper.prepareMainLooper();//創(chuàng)建 ActivityThread 線程, 并運行ActivityThread thread = new ActivityThread();//attach 方法 進行 thread 的最初初始化操作 thread.attach(false);...Looper.loop();...}//main... }//ActivityThread

② 子線程 : 子線程如果要創(chuàng)建 Handler , 需要先 調用 Looper.prepare() 方法 , 將線程轉為 Looper 線程 , 因為 創(chuàng)建 Handler 時 , 會關聯(lián)線程的 Looper 對象 , 普通的子線程是沒有 Looper 對象的 , 調用 Looper.prepare() 方法即可為該線程創(chuàng)建 Looper 對象 , 該線程也就轉為了 Looper 線程 ;

public class handler {...//獲取 Looper 對象后 , 可以從 Looper 對象中獲取 MessageQueue//關聯(lián)后 , Handler 發(fā)送消息時 , 才能將消息精準的發(fā)送給final MessageQueue mQueue;//Handler 需要與線程的唯一 Looper 對象關聯(lián)final Looper mLooper; ...public 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;...}... }

2 . Handler 對象個數(shù) : 每個 Looper 線程可以創(chuàng)建多個 Handler , 只要該 Handler 與 Looper 和 MessageQueue 關聯(lián) , 就可以將 消息 ( Message ) 發(fā)送給 Looper 線程中的 MessageQueue 中 ; Looper 輪詢該 消息隊列 ( MessageQueue ) , 將消息再次分發(fā)給對應的 Handler 進行處理 ;





IV . Looper ( 消息遍歷者 )



1 . Looper 線程 : 如果要將 Handler , Looper 機制引入到線程中 , 使某線程具有接收 Message ( 消息 ) , 執(zhí)行某項操作的功能 , 需要將該線程轉為 Looper 線程 ;


2 . Looper 線程可執(zhí)行的操作 : 一個線程如果被轉為 Looper 線程 , 那這個線程運行后只能接收 Message 消息 , 執(zhí)行對應的操作 , 運行后永遠卡在 loop 循環(huán)遍歷的 while (true) 循環(huán)中 , 使用 quit() 方法才能退出 ;


3 . Loop.prepare() 方法 : 該方法是將 普通子線程 轉為 Looper 線程最終要的方法 , 該方法的主要作用是 創(chuàng)建 Looper , 然后將 Looper 對象放入 ThreadLocal 對象中存儲 ; 線程只有創(chuàng)建了 Looper 對象才能創(chuàng)建 Handler , 將該 Looper 對象及其中封裝的 MessageQueue 與 Handler 進行關聯(lián) , Handler 才可以進行消息的調度 ; 如果線程中沒有 Looper 對象 , 創(chuàng)建 Handler 會報運行時異常 ;

public final class Looper {...// sThreadLocal.get() will return null unless you've called prepare().@UnsupportedAppUsagestatic final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();...private static void prepare(boolean quitAllowed) {if (sThreadLocal.get() != null) {throw new RuntimeException("Only one Looper may be created per thread");}sThreadLocal.set(new Looper(quitAllowed));}... }

4 . Loop.loop() 方法 : 一旦調用了該方法 , 就意味著該 Looper 線程進入到了輪詢 MessageQueue 的階段 , 這是一個無限死循環(huán) , 調用了該方法后 , Handler 發(fā)送消息 , 線程才能處理對應的業(yè)務邏輯 ;


調用 quit() 方法 , 可以終止該遍歷 MessageQueue 操作 ;

下面代碼刪除了大部分代碼 , 只留下 循環(huán)遍歷 和 調度 Message 信息給 Handler 進行處理 ;

public static void loop() {final Looper me = myLooper();...final MessageQueue queue = me.mQueue;...for (;;) {Message msg = queue.next(); // 阻塞if (msg == null) {// 循環(huán)遍歷退出return;}...try {//調度 Message 信息給 Handler 進行處理 msg.target.dispatchMessage(msg);...} ...} }



V . Looper 子線程



1 . Looper 線程就是在普通線程的基礎是哪個 , 加入了 Looper 用于消息調度 , 然后將消息轉發(fā)給 Handler 進行處理 , 這樣就實現(xiàn)了 在其它線程中 , 將任務異步分配給該 Looper 線程 ;


2 . Android 中的主線程本身就是 Looper 線程 , 整個 Looper 循環(huán)遍歷消息的過程由系統(tǒng)完成 , 用戶只需要自定義一個 Handler 成員 , 即可在子線程中調用該 Handler 將消息發(fā)送到主線程 , 在主線程執(zhí)行相關操作 , 實現(xiàn)了將異步任務分配給主線程 , 這是子線程刷新 UI 的重要途徑 ;



3 . 普通子線程 轉為 Looper 子線程 流程 :


① 定義 Handler 成員變量 : 在線程 Thread 派生類中 , 定義 Handler 類型的成員變量 ;

② Looper 初始化 : 調用 Looper.prepare() 靜態(tài)方法 , 該方法的作用是創(chuàng)建 Looper 變量 , 存儲在了 ThreadLocal 中 , 將當前普通線程轉為 Looper 線程 ;

③ 實例化 Handler 成員 : 一定要在 Looper.prepare() 之后實例化成員 , 因為如果在之前實例化 , Handler 與 Looper 無法產生關聯(lián) ;

④ 輪詢消息隊列 : 調用 Looper.loop() 方法 , 輪詢消息隊列 ( MessageQueue ) ;



4 . 實例化 Handler 成員時機 :


① 實例化時機 : 必須要在調用 Looper.prepare() 之后實例化才可以 , 因為實例化 Handler 對象時 , 會獲取當前線程的 Looper , 如果為空 , 直接拋異常 ;

② Looper 對象創(chuàng)建 : Looper.prepare() 的作用就是創(chuàng)建 Looper 對象 , 將其放入 ThreadLocal 對象中存儲 , 保證線程有且只有一個 Looper 對象 ;

public class handler {...//獲取 Looper 對象后 , 可以從 Looper 對象中獲取 MessageQueue//關聯(lián)后 , Handler 發(fā)送消息時 , 才能將消息精準的發(fā)送給final MessageQueue mQueue;//Handler 需要與線程的唯一 Looper 對象關聯(lián)final Looper mLooper; ...public 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;...}... }

5 . 普通子線程 轉為 Looper 子線程 代碼示例 :


package kim.hsl.handler;import android.os.Handler; import android.os.Looper; import android.os.Message;import androidx.annotation.NonNull;/*** 將普通線程轉為 Looper 線程** 1. 定義 Handler 成員 ( 可以定義若干個 )* 2. Looper.prepare()* 3. 實例化 Handler 成員* 4. Looper.loop()** @author hsl*/ public class LooperThread extends Thread {/*** 1. 定義時不要實例化* Handler 實例化需要關聯(lián) Looper 對象* Looper 對象在 Looper*/private Handler handler;@Overridepublic void run() {super.run();//2. 將線程轉為 Looper 線程//主要是創(chuàng)建 Looper 放入 ThreadLocal 對象中Looper.prepare();//3. 創(chuàng)建 Handler 必須在 Looper.prepare() 之后, 否則會崩潰handler = new Handler(){@Overridepublic void handleMessage(@NonNull Message msg) {super.handleMessage(msg);//TODO 處理 Handler 相關業(yè)務邏輯}};//4. Looper 開始輪詢 MessageQueue, 將消息調度給 Handler 處理Looper.loop();}public Handler getHandler() {return handler;}public void setHandler(Handler handler) {this.handler = handler;} }



VI . Handler 發(fā)送 消息 種類



Handler 既可以發(fā)送靜態(tài)的 消息 ( Message ) , 又可以發(fā)送動態(tài)的 操作 ( Runnable ) ;


當 Handler 所在的 Looper 線程接收到 消息 ( Message ) 時 , Looper 輪詢到該 消息 ( Message ) 后 , 執(zhí)行該消息對應的業(yè)務邏輯 , 這些邏輯一般都是在 Handler 中提前定義好的 ;

當 Handler 所在的 Looper 線程接收到 操作 ( Runnable ) 時 , Looper 輪詢到該 操作 ( Runnable ) 后 , 直接運行該 Runnable 中的 run() 方法 ;





VII . Handler 機制總結



1 . Handler 機制運行流程 : Message 通過 Handler 發(fā)送給 Looper 線程的 MessageQueue , Looper 輪詢 MessageQueue 將 Message 交給 Handler 執(zhí)行 ;


2 . 線程異步調用 ( 作用 ) : 子線程刷新主線程 UI ( 子線程調用主線程 ) , 主線程調用子線程異步網絡操作 ( 主線程調用子線程 ) ;


3 . 子線程轉 Looper 線程 : 定義Handler 成員 ( 可以多個 ) , Loop.prepare() , Handler 初始化 ( 必須在 prepare 之后 ) , Looper.loop() ;


4 . 四組件關系 : 111線程 ?\Leftrightarrow? 111 Looper ?\Leftrightarrow? 111 MessageQueue ?\Leftrightarrow? nnn Handler ?\Leftrightarrow? mmm Message ;

總結

以上是生活随笔為你收集整理的【Android】Handler 机制 ( Handler | Message | Looper | MessageQueue )的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。