【Android 异步操作】手写 Handler ( Message 消息 | ThreadLocal 线程本地变量 | Looper 中的消息队列 MessageQueue )
文章目錄
- 一、Message 消息
- 二、ThreadLocal 線程本地變量
- 三、Looper 中的消息隊(duì)列 MessageQueue
一、Message 消息
模仿 Android 中的 Message 基本功能 , 提供 what 與 obj 變量 , 提供一個(gè)回收方法 ;
此外 , 還要指明下一個(gè)消息 , 以及是哪個(gè) Handler 發(fā)送的該消息 ;
package kim.hsl.handler;public class Message {/*** 消息識(shí)別碼*/int what;/*** 消息對(duì)象*/Object obj;/*** 指向下一個(gè)消息*/Message next;/*** 該 Message 使用哪個(gè) Handler 進(jìn)行發(fā)送的*/Handler target;/*** 回收方法*/public void recyle(){obj = null;next = null;target = null;} }二、ThreadLocal 線程本地變量
ThreadLocal 作用是 保存線程私有變量 ;
使用 ThreadLocal 維護(hù)一個(gè)變量時(shí) , 每個(gè)使用該 ThreadLocal 線程本地變量 的線程 , 都會(huì) 被分配一個(gè)獨(dú)立的變量副本 ,
每個(gè)線程 只 可以 改變本線程內(nèi)的 變量副本 , 即 ThreadLocal 線程本地變量 ;
1 . ThreadLocal 定義 :
/*** 一個(gè)線程只能有一個(gè) Looper* 使用 ThreadLocal 來保存該 Looper* 該變量是線程內(nèi)部存儲(chǔ)類 , 只能本線程才可以得到存儲(chǔ)的數(shù)據(jù) ;*/static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>();2 . ThreadLocal 變量獲取 : 調(diào)用 ThreadLocal 變量的 get() 方法 , 可以獲取該 ThreadLocal 線程本地變量 ;
在 ThreadLocalMap map = getMap(t) 中 , 獲取的 ThreadLocalMap 與 Java 中的 Map 集合沒有任何關(guān)聯(lián) , 該類就是為了保存 線程本地變量而在 ThreadLocal 中設(shè)置的內(nèi)部類 ; 在該 ThreadLocalMap 內(nèi)部類中 , 通過 key 鍵 , 獲取對(duì)應(yīng) value 值 ;
public class ThreadLocal<T> {/*** 返回 該線程本地變量的 當(dāng)前線程的變量副本.* 如果 該線程中對(duì)應(yīng)的 變量沒有值, 應(yīng)該首先初始化該變量值** @return 返回當(dāng)前線程的線程本地變量值 */public T get() {// 首先通過 Thread 拿到當(dāng)前的線程 Thread t = Thread.currentThread();// 通過當(dāng)前線程 , 獲取當(dāng)前線程的 ThreadLocalMap ThreadLocalMap map = getMap(t);if (map != null) {// 通過 key 獲取指定的 valueThreadLocalMap.Entry e = map.getEntry(this);if (e != null) {@SuppressWarnings("unchecked")T result = (T)e.value;return result;}}return setInitialValue();} }3 . ThreadLocal 變量設(shè)置 : 調(diào)用 ThreadLocal 的 put() 方法 , 可以設(shè)置 線程本地變量 ;
4 . Looper 中關(guān)于 線程本地變量 的設(shè)置 : 在 Looper 中涉及到了 線程本地變量 的設(shè)置 ,
Looper 要求每個(gè)線程只能保持一個(gè) , 并且各個(gè)線程之間的 Looper 相互獨(dú)立 , 沒有任何關(guān)聯(lián) ;
這就需要 將 Looper 定義成線程本地變量 ;
public class Looper {/*** 一個(gè)線程只能有一個(gè) Looper* 使用 ThreadLocal 來保存該 Looper* 是線程內(nèi)部存儲(chǔ)類 , 只能本線程才可以得到存儲(chǔ)的數(shù)據(jù) ;*/static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>();/*** 準(zhǔn)備 Looper 方法* 其中* 使用了 sThreadLocal.get() 獲取線程本地變量 * 使用了 sThreadLocal.set(new Looper()) 設(shè)置線程本地變量 */public static void prepare(){// 先進(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 中首先要維護(hù)一個(gè) ThreadLocal 線程本地變量 , 確保每個(gè)線程中都可以獲取到一個(gè)該變量的獨(dú)立副本 ;
維護(hù)消息隊(duì)列 : 每個(gè) Looper 中還要維護(hù)一個(gè) MessageQueue 消息隊(duì)列 , 用于存儲(chǔ)從 Handler 中發(fā)送來的消息 ;
該消息隊(duì)列 在 Looper 初始化時(shí)創(chuàng)建 ;
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(){// 先進(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());}}總結(jié)
以上是生活随笔為你收集整理的【Android 异步操作】手写 Handler ( Message 消息 | ThreadLocal 线程本地变量 | Looper 中的消息队列 MessageQueue )的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Android 异步操作】Handle
- 下一篇: 【Android 高性能音频】Oboe