日韩性视频-久久久蜜桃-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 )的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 日韩爽片 | 操极品少妇 | 五月天激情啪啪 | 国产av一区二区三区传媒 | 国产色呦呦| 狼人综合伊人 | 99国产精品久久久久99打野战 | 老司机亚洲精品 | 成人三级在线播放 | 善良的公与媳hd中文字 | 伊人av在线 | 丁香六月激情综合 | 大尺度叫床戏做爰视频 | 一级片在线观看视频 | 国产主播av在线 | 国产精品高潮呻吟久久久 | 日韩电影一二三区 | 日韩中文字幕不卡 | 在线观看的av网址 | 免费在线看黄视频 | 免费播放毛片 | 自由成熟xxxx色视频 | 欧美性猛交xxxx乱大交俱乐部 | 成人片在线看 | china国模大尺度pics | 精品三级电影 | 日韩h视频 | 日韩一级在线视频 | 亚洲精品鲁一鲁一区二区三区 | 高清毛片aaaaaaaaa郊外 | 青青草原伊人 | 一区二区中文字幕 | 久久黄色录像 | 欧美久草视频 | 成人免费va视频 | 亚洲人一区二区三区 | 日韩精品中文字幕一区 | 天天射夜夜操 | 久久久久国产一区 | 91精品免费在线观看 | 小箩莉末发育娇小性色xxxx | 午夜窝窝| 91看片免费版 | 奇米888一区二区三区 | 性的免费视频 | 亚洲视频欧美 | 欧美日韩综合在线 | 久久亚洲婷婷 | 黄色xxx| 日日操视频 | 中文字幕 人妻熟女 | 色婷视频 | 毛片在线看片 | 日韩色区| 人人插人人草 | 中国一级免费毛片 | av涩涩 | 亚洲黄色片 | 91粉色视频| 欧美a级黄色片 | 在线成人福利 | 97影院 | 美利坚合众国av | 国产成人手机在线 | 欧美精品一区二区三区蜜臀 | 四虎影视在线播放 | 国产激情在线 | 美女视频黄a视频全免费观看 | 国产亚洲制服 | 日本黄色a视频 | 婷婷亚洲综合五月天小说 | 久久av不卡 | 亚洲最大视频网 | 丰满肉嫩西川结衣av | 国际av在线 | 亚洲色图一区二区 | 国产免费无遮挡吸奶头视频 | 国产二级一片内射视频播放 | 97久久国产精品 | 亚洲天堂性 | 国产在线二区 | 91色在线视频 | 久久99久久久久久 | 日本视频在线免费观看 | www.我爱av | 国产亚洲精品精品国产亚洲综合 | 丰满少妇一区二区三区专区 | 婷婷午夜激情 | 亲嘴扒胸摸屁股激烈网站 | 中文字幕无码乱人伦 | 亚洲国产成人在线 | 日本视频免费在线 | 国产中文字幕在线视频 | 欧美精品一区二 | 一区二区的视频 | 青青青视频在线 | 亚洲视频播放 | 久久电影一区 | 涩涩片影院 |