Android源碼閱讀之Handler

Android的消息機制主要基於Handler,Looper,Messagequeue,Message之間的協同,消息機制主要用於線程切換操作或者延時任務,一般應用場景爲子線程發起網絡請求,攜帶網絡請求結果通知主線程更新UI。下面,我們通過源碼來看下Handler類

Handler在消息機制中的作用是發送消息並且處理消息,常用創建Handler對象的方式有兩種:

1.第一種是採用匿名內部類的方式(派生出一個Handler的子類,並且重寫handleMessage方法)

Handler handler=new Handler()

{

    @Override
    
    public void handleMessage(Message msg) {

    super.handleMessage(msg);

    }
};

2.第二種是通過接口監聽的方式來創建,實現Hanlder.callback接口的方法

Handler handler=new Handler(new Handler.Callback() {

    @Override

    public boolean handleMessage(Message msg) {

    return false;

    }

});

構造函數

接下來我們進入Handler的構造方法看下 首先看下Handler()

public Handler() {

    this(null, false);

}

以及Handler(callback)

public Handler(Callback callback) {

    this(callback, false);

}

我們可以看到這兩個構造方法裏面都執行的其實是另外一個構造方法

public Handler(Callback callback, boolean async) {

    if (FIND_POTENTIAL_LEAKS) {

        final Class<? extends Handler> klass = getClass();

        if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass())     &&(klass.getModifiers() & Modifier.STATIC) == 0) {

        Log.w(TAG, "The following Handler class should be static or leaks might occur: "     + klass.getCanonicalName());

        }

    }

    mLooper = Looper.myLooper();

    if (mLooper == null) {

        throw new RuntimeException(

    "Can't create handler inside thread that has not called Looper.prepare()");

    }

    mQueue = mLooper.mQueue;

    mCallback = callback;
    
    mAsynchronous = async;

}

在上面的這個構造函數 我們可以看到Handler類持有Looper,Messagequeue對象的引用,但是在Handler類中

Looper的作用很簡單,就是得到Looper所創建的messagequeue對象的引用賦值給Handler類的mqueue變量,

因爲handler發送消息就是將消息添加到messagequeue鏈表中,調用messagequeue.enqueueMessage方法

Looper.myLooper()方法是從ThreadLocal<Looper>中得到當前線程保存的Looper對象(ps:Looper後面會涉及到)

發送消息

看完構造函數,接下來看下handler主要的也是我們一般情況下使用的sendMessage發送消息的方法

sendMessage方法調用鏈

sendMessage(Message msg)

-> sendMessageDelayed(Message msg, long delayMillis)

->sendMessageAtTime(Message msg, long uptimeMillis)

->enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)

可以看到 最終調用的是enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)這個方法

不止是sendMessage方法,像Handler的Post/PostDelayed方法都是構建一個message並最終調用enqueueMessage方法

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {

    msg.target = this;

    if (mAsynchronous) {

        msg.setAsynchronous(true);

    }

    return queue.enqueueMessage(msg, uptimeMillis);

}

如上代碼所示 msg.target = this; 將message的Handler類型變量target引用指向當前的Handler

最後調用messagequeue的enqueueMessage(msg, uptimeMillis)方法 將msg添加到messagequeue中去

處理消息

接下來到了Handler另一個重要的地方 就是處理消息

在Looper循環從MessageQueue隊列中取到新Message會調用

msg.target.dispatchMessage(msg) 上面我們說過msg.target指向的是當前的Handler

所以Handler的dispatchMessage方法會被觸發 看下代碼

public void dispatchMessage(Message msg) {

    if (msg.callback != null) {

        handleCallback(msg);

    } else {

        if (mCallback != null) {

            if (mCallback.handleMessage(msg)) {

                return;
            }

        }

        handleMessage(msg);

   }

}

首先說明一下 msg.callback是Runnable類 也是post(Runnable r)或者postDelayed(Runnable s,time d)中的Runnable的對象,如果不爲空,則會handleCallback調用

private static void handleCallback(Message message) {

    message.callback.run();

}

這裏仔細看 是調用的Runnable的run方法,並不是start方法,並不會新創建一個線程

如果msg.callback爲空 則判斷mCallback(Handler.Callback) 是否爲空

不爲空 則調用mCallback.handleMessage

爲空 則調用handleMessage(msg)

此處可以看構造方法那一塊

 

Handle總結

Handler是消息機制很重要的一環,發送消息/延時任務和處理消息都在Handler中處理,

主要借用Messagequeue將消息添加到Message鏈表的數據結構中去,由Looper取出消息

並回到Handler中去處理對應的邏輯

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章