Android 訊息處理機制淺析
Android是訊息驅動的,實現訊息驅動有幾個要素:
訊息的表示:Message
訊息佇列:MessageQueue
訊息迴圈,用於迴圈取出訊息進行處理:Looper
訊息處理,訊息迴圈從訊息佇列中取出訊息後要對訊息進行處理:Handler
平時我們最常使用的就是Message與Handler了,如果使用過HandlerThread或者自己實現類似HandlerThread的東西可能還會接觸到Looper,而MessageQueue是Looper內部使用的,對於標準的SDK,我們是無法例項化並使用的(建構函式是包可見性)。
我們平時接觸到的Looper、Message、Handler都是用JAVA實現的,Android做為基於Linux的系統,底層用C、C++實現的,而且還有NDK的存在,訊息驅動的模型怎麼可能只存在於JAVA層,實際上,在Native層存在與Java層對應的類如Looper、MessageQueue等。
本文根據網上現有資源進行整合,以及自己的理解,有誤之處歡迎指正~~
一、Handle 的使用場景
執行緒安全問題的引入: 多個執行緒併發的操作UI元件,可能導致執行緒安全問題的出現
什麼是UI執行緒: 當App第一次啟動時,Android會同時啟動一條UI執行緒(主執行緒),負責處理與UI相關的事件,比如觸發事件,修改UI元件等
Android提供的解決機制: 只允許在UI執行緒中修改Activity中的元件
但是,如果要讓新啟動的執行緒週期性的修改UI元件的屬性值,怎麼辦?就使用到Handle類
二、Handle 的訊息處理機制
在Android中提供了一種非同步回撥機制Handler,
說明:
UI執行緒:就是我們的主執行緒,系統在建立UI執行緒的時候會初始化一個Looper物件,同時也會建立一個與其關聯的MessageQueue;
Handler:作用就是傳送與處理資訊,如果希望Handler正常工作,在當前執行緒中要有一個Looper物件
Message:Handler接收與處理的訊息物件
MessageQueue:訊息佇列,先進先出管理Message,在初始化Looper物件時會建立一個與之關聯的MessageQueue;
Looper:每個執行緒只能夠有一個Looper,管理MessageQueue,不斷地從中取出
通俗一點講:當我們的子執行緒想修改Activity中的UI元件時,我們可以新建一個Handler物件,通過這個物件向主執行緒傳送資訊;而我們傳送的資訊會先到主執行緒的MessageQueue進行等待,由Looper按先入先出順序取出,再根據message物件的what屬性分發給對應的Handler進行處理.
三、Handler的相關方法
在使用android的訊息的處理機制的時候:一般是有兩種手段,
1、該message自己繫結到目標handler後,自行進入messageQueue,等待handler接受處理。Message方法:public static Message obtain(Handler h, int what, int arg1, int arg2, Object obj) ,通過該方法可以獲得一個訊息:Message message = Message.obtain(handler, 33, 2, 3, "hello");
傳送訊息的方式,有一點將自己繫結好了被髮射的感覺,message.sendToTarget(); ---被動(意會)
2、handler主動設定要傳送的訊息的各個屬性值:arg1,arg2,obj,what。方法:public final Message obtainMessage(int what, int arg1, int arg2, Object obj) 通過該方法也可以獲得一個訊息:比如Message message = handler.obtainMessage(3, 1, 2, "java");
然後將設定好的訊息,由handler傳送出去:handler.sendMessage(message);----主動(自己意會的)。下面十幾個常用方法:
void handleMessage(Message msg):處理訊息的方法,使用handleMessage去處理訊息,裡面的引數Message msg既是在messageQueue裡面取出的訊息message~
sendEmptyMessage(int what):傳送空訊息
sendEmptyMessageDelayed(int what,long delayMillis):指定延時多少毫秒後傳送空資訊
sendMessage(Message msg):立即傳送資訊
sendMessageDelayed(Message msg):指定延時多少毫秒後傳送資訊
final boolean hasMessage(int what):檢查訊息佇列中是否包含what屬性為指定值的訊息 如果是引數為(int what,Object object):除了判斷what屬性,還需要判斷Object屬性是否為指定物件的訊息