Handler建立的幾個必備知識點,瞭解一下

語言: CN / TW / HK

highlight: vs theme: devui-blue


持續創作,加速成長!這是我參與「掘金日新計劃 · 10 月更文挑戰」的第8天,點選檢視活動詳情

本篇文章主要介紹Handler中需要了解的幾個必備知識點,比如Handler建立非同步Handler是個啥及如何建立。

普通Handler建立

一般下面這樣建立Handler時AS會進行告警:

image.png

刪除線提示Handler的無參構造方法已經被@Deprecated標記,正確的做法都是使用帶Looper構造引數的構造方法進行Handler的建立:

image.png

這樣做的好處是直接指定訊息排程在哪個Looper,而Looper是通過ThreadLocal和執行緒繫結在一起,也就是說,指明瞭Looper就能知道當前訊息Message最終會在哪個執行緒中執行。

而之所以Handler無參構造方法被廢棄的一個原因就是:

它會嘗試從當前執行緒中的ThreadLocal獲取Looper,主執行緒會自動幫助我們建立好Looper自然是沒什麼問題,但是如果子執行緒中執行Handler的建立,而沒有手動呼叫Looper.prepare(),就會導致崩潰。

非同步Handler的使用及建立

非同步Handler有什麼作用呢,相比較於普通Handler,可以獲取優先排程執行權,當前,前提是要新增同步屏障訊息。

這裡解釋下同步屏障訊息:

同步屏障訊息和普通的Message基本上沒啥區別,主要的一個區分點是同步屏障訊息Messagetarget屬性為null,當從訊息佇列中取出訊息並執行時,會先判斷下當前的Messagetarget是否為null,如果為null則會從訊息佇列中優先獲取非同步訊息 進行排程執行

相應的原始碼如下:

image.png

新增訊息屏障的方法為MessageQueue.postSyncBarrier(),不過這個方法目前是不支援業務方直接進行呼叫。

上面訊息屏障說完了,我們接下來看下非同步訊息如何建立:非同步訊息的建立依賴非同步Hanlder的建立。所以我們看下非同步Handler如何進行建立:

```java @NonNull public static Handler createAsync(@NonNull Looper looper) { if (looper == null) throw new NullPointerException("looper must not be null"); return new Handler(looper, null, true); }

@NonNull public static Handler createAsync(@NonNull Looper looper, @NonNull Callback callback) { if (looper == null) throw new NullPointerException("looper must not be null"); if (callback == null) throw new NullPointerException("callback must not be null"); return new Handler(looper, callback, true); } ```

Handler提供了createAsync()兩個過載方法進行建立,最終會將HandlermAsynchronous屬性置為true,然後通過Hanlder傳送訊息時,最終會走到Handler.enqueueMessage()方法:

java private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg, long uptimeMillis) { ... if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }

可以看到,如果mAsynchronous屬性為true,就將Message新增FLAG_ASYNCHRONOUS置為非同步訊息。不過這個API是隻有在SDK>=28以上才能呼叫,那麼訊息28的版本如何建立的,這裡給出一個非常全面的相容各個SDK版本的建立非同步Handler的方法:

image.png

上面的使用講完了,說下應用了。這個非同步訊息+訊息屏障在系統原始碼中有一個非常典型的應用場景,那就是介面的繪製

image.png

由於介面的繪製渲染優先順序是比較高的,所以新增訊息屏障後,將繪製相關的Message指定為非同步方式,就可以優先進行執行。

總結

本篇文章主要是詳細介紹了普通Hanlder非同步Hanlder的建立方式及使用場景,希望能給大家帶來幫助。