【Android 异步操作】手写 Handler ( 循环者 Looper | Looper 初始化 | Looper 遍历消息队列 MessageQueue )
文章目錄
- 一、Looper 初始化
- 二、Looper 遍歷消息隊(duì)列 MessageQueue
- 三、完整 Looper 代碼
一、Looper 初始化
Looper 是 線程本地變量 , 在每個(gè)線程中 , 可以通過線程調(diào)用 ThreadLocal 變量的 get 方法獲取該線程對(duì)應(yīng)的對(duì)象副本 , 調(diào)用 ThreadLocal 變量的 set 方法 , 設(shè)置該線程對(duì)應(yīng)類型的對(duì)象副本 ;
Looper 調(diào)用 prepare 方法進(jìn)行初始化 , 在該方法中處理 線程本地變量的先關(guān)初始化與設(shè)置 ,
如果之前已經(jīng)初始化過 , 本次調(diào)用 prepare 方法是第二次調(diào)用 , 則會(huì) 拋出異常 ,
如果之前沒有初始化過 , 那么創(chuàng)建一個(gè) Looper , 然后調(diào)用線程本地變量 ThreadLocal 的 set 方法 , 將該 Looper 對(duì)象設(shè)置成線程本地變量 ;
/*** 一個(gè)線程只能有一個(gè) Looper* 使用 ThreadLocal 來保存該 Looper* 是線程內(nèi)部存儲(chǔ)類 , 只能本線程才可以得到存儲(chǔ)的數(shù)據(jù) ;*/static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>();/*** 準(zhǔn)備 Looper 方法*/public static void prepare(){System.out.println("prepare 創(chuàng)建 Looper ");// 先進(jìn)行判斷 , 如果當(dāng)前線程已經(jīng)有了 Looper , 那就拋出異常if(sThreadLocal.get() != null){throw new RuntimeException("當(dāng)前線程已存在 Looper");}// 如果不存在 Looper , 就創(chuàng)建一個(gè) LoopersThreadLocal.set(new Looper());}二、Looper 遍歷消息隊(duì)列 MessageQueue
在 Looper 線程中 , 最后一句代碼肯定是 Looper.loop() , 執(zhí)行該方法后 , 就開啟了一個(gè)無限循環(huán) ,
不斷從 消息隊(duì)列 MessageQueue 中獲取消息 , 然后發(fā)送給該 消息 Message 對(duì)應(yīng)的 Handler ,
哪個(gè) Handler 發(fā)送的消息 , 就將消息在送回給哪個(gè) Handler ;
消息同步 : 當(dāng) 消息隊(duì)列 MessageQueue 為空時(shí) , 無法從消息隊(duì)列中獲取數(shù)據(jù) , 此時(shí)線程會(huì) 阻塞 , 直到有新的消息到來后 , 解除阻塞 ;
Looper 循環(huán)遍歷消息隊(duì)列部分代碼 :
/*** 不斷從 消息隊(duì)列 MessageQueue 中取出 Message 消息執(zhí)行*/public static void loop(){System.out.println("開始無限循環(huán)獲取 Message");// 獲取當(dāng)前線程的 LooperLooper looper = Looper.looper();// 從當(dāng)前線程的 Looper 獲取 消息隊(duì)列 MessageQueueMessageQueue messageQueue = looper.mQueue;// 不斷從 消息隊(duì)列中獲取 消息 , 分發(fā)到發(fā)送消息的 Handler 中執(zhí)行for(;;){// 獲取消息隊(duì)列中的第一個(gè)消息Message next = messageQueue.next();// 分發(fā)到發(fā)送該消息的 Handler 中執(zhí)行next.target.handleMessage(next);}}三、完整 Looper 代碼
package kim.hsl.handler;public class Looper {/*** 一個(gè)線程只能有一個(gè) Looper* 使用 ThreadLocal 來保存該 Looper* 是線程內(nèi)部存儲(chǔ)類 , 只能本線程才可以得到存儲(chǔ)的數(shù)據(jù) ;*/static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>();/*** 消息隊(duì)列*/public MessageQueue mQueue;/*** Looper 構(gòu)造函數(shù)*/private Looper(){mQueue = new MessageQueue();}/*** 獲取當(dāng)前線程對(duì)應(yīng)的 Looper* @return*/public static Looper looper(){return sThreadLocal.get();}/*** 準(zhǔn)備 Looper 方法*/public static void prepare(){System.out.println("prepare 創(chuàng)建 Looper ");// 先進(jìn)行判斷 , 如果當(dāng)前線程已經(jīng)有了 Looper , 那就拋出異常if(sThreadLocal.get() != null){throw new RuntimeException("當(dāng)前線程已存在 Looper");}// 如果不存在 Looper , 就創(chuàng)建一個(gè) LoopersThreadLocal.set(new Looper());}/*** 不斷從 消息隊(duì)列 MessageQueue 中取出 Message 消息執(zhí)行*/public static void loop(){System.out.println("開始無限循環(huán)獲取 Message");// 獲取當(dāng)前線程的 LooperLooper looper = Looper.looper();// 從當(dāng)前線程的 Looper 獲取 消息隊(duì)列 MessageQueueMessageQueue messageQueue = looper.mQueue;// 不斷從 消息隊(duì)列中獲取 消息 , 分發(fā)到發(fā)送消息的 Handler 中執(zhí)行for(;;){// 獲取消息隊(duì)列中的第一個(gè)消息Message next = messageQueue.next();// 分發(fā)到發(fā)送該消息的 Handler 中執(zhí)行next.target.handleMessage(next);}}}
總結(jié)
以上是生活随笔為你收集整理的【Android 异步操作】手写 Handler ( 循环者 Looper | Looper 初始化 | Looper 遍历消息队列 MessageQueue )的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Android 异步操作】手写 Han
- 下一篇: 【Android 异步操作】手写 Han