Handler的使用及原理

Handler作用:

因為在Android中,主線程不建議做耗時的操作,子線程不建議更新UI,但是Android開發,其實就是搭建好頁面,將服務器的數據展示到頁面上,所以我網絡請求使用會非常頻繁,而網絡請求屬于耗時操作,需要放到子線程完成,但一般情況下也不會通過子線程更新UI,需要將請求成功的數據發送到主線程進行UI更新,所以一般會使用到handler。

Handler執行流程:

首先handler作為任務執行者,一般創建在主線程,當子線程有需要發送的數據,通過創建message對象,使用handler對象將消息發送到messagequeue,messagequeue遵循了隊列先進先出的原則,當主線程的looper循環消息的時候,會按照messagequeue隊列的順序循環消息,并將消息給到任務執行者handler去執行任務。


Handler執行原理:

Handler創建完成后,內部的Looper以及MessageQueue就可以和Handler一起協同工作,然后通過Hadler的post方法將一個Runnable投遞到Handler內部的Looper中去處理,也可以通過Handler的send方法發送一個消息,這個消息會在Looper中做處理。Post最終也是通過send來完成的。當Handler的send方法被調用時,他會調用MessageQueue的enqueueMessage方法將這個消息放入消息隊列中,然后Looper發現有新消息到來時,就會處理這個消息,最終消息中的Runnable或者Handler的handlerMessage方法就會被調用。Looper試運行在Handler所在的線程,所以就把業務邏輯切換到主線程了

Handler最常規的使用方式:

private Handler mHandler = new Handler(){?

@Override

public void handleMessage(Message msg) {

super.handleMessage(msg);

switch (msg.what) {

case MESSAGE_WHAT:

Log.d(TAG, "main thread receiver message: " + ((String) msg.obj)); break;

????????}

????}

};

? ? private void sendMessageToMainThreadByWorkThread() {?

? ? ? new Thread(){? ?

? ? ? ? @Override?

? ? ? ? ? public void run() {?

? ? ? ? ? ? ? Message message = mHandler.obtainMessage(MESSAGE_WHAT);

? ? ? ? ? ? ? ? message.obj = "I am message from work thread";?

? ? ? ? ? ? ? mHandler.sendMessage(message);? ?

? ? ? ? }? ?

? ? }.start();?

? }


/*

? ? * 通常我們在主線程中創建一個Handler,

? ? * 然后重寫該Handler的handlerMessage方法,可以看到該方法傳入了一個參數Message,

? ? * 該參數就是我們從其他線程傳遞過來的信息。

? ? * 我們在來看下子線程中如何傳遞的信息,子線程通過Handler的obtainMessage()方法獲取到一個Message實例,

? ? * 我們來看看Message的幾個屬性:

? ? * Message.what------------------>用來標識信息的int值,通過該值主線程能判斷出來自不同地方的信息來源

? ? * Message.arg1/Message.arg2----->Message初始定義的用來傳遞int類型值的兩個變量

? ? * Message.obj------------------->用來傳遞任何實例化對象

? ? * 最后通過sendMessage將Message發送出去。

*/


Handler補充:

1. Handler在使用過程中,需要注意的問題之一便是內存泄漏問題。

為什么會出現內存泄漏問題呢?

首先Handler使用是用來進行線程間通信的,所以新開啟的線程是會持有Handler引用的,

如果在Activity等中創建Handler,并且是非靜態內部類的形式,就有可能造成內存泄漏。

首先,非靜態內部類是會隱式持有外部類的引用,所以當其他線程持有了該Handler,線程沒有被銷毀,則意味著Activity會一直被Handler持有引用而無法導致回收。

同時,MessageQueue中如果存在未處理完的Message,Message的target也是對Activity等的持有引用,也會造成內存泄漏。

解決的辦法:

?(1). 使用靜態內部類+弱引用的方式:

? 靜態內部類不會持有外部類的的引用,當需要引用外部類相關操作時,可以通過弱引用還獲取到外部類相關操作,弱引用是不會造成對象該回收回收不掉的問題

(2). 在外部類對象被銷毀時,將MessageQueue中的消息清空。例如,在Activity的onDestroy時將消息清空。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。