Handler機制 4 Looper簡介

2021-10-21 11:57:21 字數 3324 閱讀 8197

四、looper

概述looper可以說是handler機制中的乙個非常重要的核心。looper相當於執行緒訊息機制的引擎,驅動整個訊息機制執行。looper負責從佇列中取出訊息,然後交給對應的handler去處理。如果佇列中沒有訊息,則messagequeue的next方法會阻塞執行緒,等待新的訊息的到來。每個執行緒有且只能有乙個「引擎」,也就是looper,如果沒有looper,那麼訊息機制就執行不起來,而如果有多個looper,則會違背單線操作的概念,造成併發操作。

每個執行緒僅有乙個looper,由不同looper分發的message執行在不同的執行緒中。looper的內部維護乙個messagequeue,當初始化looper的時候會順帶初始化messagequeue。

looper使用threadlocal來保證每個執行緒都有且只有乙個相同的副本。

關鍵方法

prepare : 初始化looper

looper.class

static final threadlocalsthreadlocal = new threadlocal();

public static void prepare()

// 最終呼叫到了這個方法

private static void prepare(boolean quitallowed)

sthreadlocal.set(new looper(quitallowed));

}每個執行緒使用handler之前,都必須呼叫looper.prepare()方法來初始化當前執行緒的looper。引數quitallowed表示該looper是否可以退出。主線程的looper是不能退出的,不然程式就直接終止了。我們在主線程使用handler的時候是不用初始化looper的,為什麼?因為activiy在啟動的時候就已經幫我們初始化主線程looper了,這點在後面再詳細展開。所以在主線程我們可以直接呼叫looper.mylooper()獲取當前執行緒的looper。

prepare方法重點在sthreadlocal.set(new looper(quitallowed));,可以看出來這裡使用了threadlocal來建立當前執行緒的looper物件副本。如果當前執行緒已經有looper了,則會丟擲異常。sthreadlocal是looper類的靜態變數,前面我們介紹過了threadlocal了,這裡每個執行緒呼叫一次prepare方法就可以初始化當前執行緒的looper了。

接下來再看到looper的構造方法:

private looper(boolean quitallowed) 12

34邏輯很簡單,初始化了乙個messagequeue,再把當前的執行緒的thread物件賦值給mthread。

mylooper() : 獲取當前執行緒的looper物件

獲取當前執行緒的looper物件。這個方法就是直接呼叫threadlocal的get方法:

public static @nullable looper mylooper() 12

3loop() : 迴圈獲取訊息

當looper初始化完成之後,他是不會自己啟動的,需要我們自己去啟動looper,呼叫looper的loop()方法即可:

public static void loop()

final messagequeue queue = me.mqueue;

...for (;;)

...try

dispatchend = needendtime ? systemclock.uptimemillis() : 0;

}...

// **message

msg.recycleunchecked();}}

loop()方法就是looper這個「引擎」的核心所在。首先獲取當前執行緒的looper物件,沒有則丟擲異常。然後進入乙個死迴圈:不斷呼叫messagequeue的next方法來獲取訊息,然後呼叫message的目標handler的dispatchmessage方法來處理message。

前面我們了解過了messagequeue,next方法是可能會進行阻塞的:當messagequeue為空或者目前沒有任何訊息需要處理。所以looper就會一直等待,阻塞在裡,執行緒也就不會結束。當我們退出looper的時候,next方法會返回null,那麼looper也就會跟著結束了。

同時,因為looper是執行在不同執行緒的邏輯,其呼叫的dispatchmessage方法也是執行在不同的執行緒,這就達到了切換執行緒的目的。

quit/quitsafely : 退出looper

quit是直接將looper退出,quitsafely是將messagequeue中的不需要等待的訊息處理完成之後再退出,看一下**:

public void quit()

// 最終都是呼叫到了這個方法

void quit(boolean safe)

synchronized (this)

mquitting = true;

// 執行不同的方法

if (safe) else

// 喚醒messagequeue

nativewake(mptr);}}

我們可以發現最後都呼叫了quitsafely方法。這個方法先判斷是否能退出,然後再執行退出邏輯。如果mquitting==true,那麼這裡會直接方法,我們會發現mquitting這個變數只有在這裡被執行了賦值,所以一旦looper退出,則無法再次執行了。之後執行不同的退出邏輯,我們分別看一下:

private void removeallmessageslocked()

mmessages = null;

}這個方法很簡單,直接把當前所有的message全部移除。再看一下另乙個方法:

private void removeallfuturemessageslocked() else

if (n.when > now)

p = n;

}p.next = null;

do while (n != null);}}

}這個方法邏輯也不複雜,就是把需要等待的message全部移除,當前需要執行的message則保留。最終在messagequeue的next方法中,會進行判斷後返回null,表示退出,looper收到這個返回值之後也跟著退出了。

looper總結

looper作為handler訊息機制的「動力引擎」,不斷從messagequeue中獲取訊息,然後交給handler去處理。looper的使用前需要先初始化當前執行緒的looper物件,再呼叫loop方法來啟動它。

同時handler也是實現切換的核心,因為不同的looper執行在不同的執行緒,他所呼叫的dispatchmessage方法則執行在不同的執行緒,所以message的處理就被切換到looper所在的執行緒了。當looper不再使用時,可呼叫不同的退出方法來退出他,注意looper一旦退出,執行緒則會直接結束。

handler通訊機制

android應用開發有個預設規則,不在ui執行緒做耗時操作。耗時操作結果反饋給使用者也不能直接更新ui。耗時操作必須開子執行緒去做,實現的方式很多,handler asynctask service。每個人偏好不同,但是各有各的優點,根據不同的需求選擇適當的實現方式,是我一直追求的目標,每一種至少...

Handler機制概要

簡而言之,每個thread裡面有looper 通過prepare初始化,通過loop進入死迴圈 每個handler將自己的msg放入looper死迴圈裡面,然後looper迴圈檢測訊息再傳送回給handler。記憶體洩漏問題 這裡需要注意乙個記憶體洩漏問題,就是當activity退出的時候會出現記憶...

Handler機制整理

handler機制整理 目錄介紹 1.關於handler訊息機制圖 2.關於handler基本介紹 3.使用handler的幾種方法 4.關於handler底層原始碼解讀 1.關於handler訊息機制圖 2.關於handler機制基本解讀 message 訊息,其中包含了訊息id,訊息處理物件以及...