非同步訊息處理機制

2021-07-30 21:51:27 字數 3272 閱讀 7399

[借鑑](
為什麼不能在子執行緒更新ui?

1、ui是非執行緒安全的,主線程和子執行緒同時更新ui的話會導致錯誤,如ui錯亂之類的。

2、ui更新是很耗效能的,更別說為了執行緒安全加鎖了,最簡單的方法就是更新ui的操作放到乙個執行緒中,即主線程;

handler機制:

looper:維持乙個thread物件以及messagequeue

private looper(boolean quitallowed)

1. 將執行緒物件指向了建立looper的執行緒

2. 建立了乙個新的messagequeue

1)looper.loop()(在當前執行緒啟動乙個message loop機制)

2)looper.prepare()(在當前執行緒關聯乙個looper物件)

判斷當前執行緒有木有looper,如果有則丟擲異常(在這裡我們就可以知道,android規定乙個執行緒只能夠擁有乙個與自己關聯的looper)。

如果沒有的話,那麼就設定乙個新的looper到當前執行緒。

在主線程和子執行緒分別建立handler物件,子執行緒丟擲can』t create handler inside thread that has not called looper.prepare() 。不能在沒有呼叫looper.prepare() 的執行緒中建立handler。

而主線程在程式啟動的時候,系統已經幫我們自動呼叫了looper.prepare()方法。

1、looper.prepare() 在本執行緒中儲存乙個looper例項,該例項中儲存乙個messagequeue物件,只會存在乙個

2、looper.loop()進入無線迴圈,不斷從messagequeue讀取訊息,然後回掉msg.target的dispatchmessage(msg)方法

3、handler首先得到looper例項,進而與messagequeue相關聯

4、handler的sendmessage()會給msg的target賦值為handler本身,然後加入到messagequeue中

5、構造handler例項時,會重寫handlemessage()方法,也就是msg.target的dispatchmessage(msg)方法最終呼叫的方法。

總結:當我們呼叫handler.sendmessage(msg)方法傳送乙個message時,實際上這個message是傳送到與當前執行緒繫結的乙個messagequeue中,然後與當前執行緒繫結的looper將會不斷的從messagequeue中取出新的message,呼叫msg.target.dispathmessage(msg)方法將訊息分發到與message繫結的handler.handlemessage()方法中。

為什麼使用非同步訊息處理的方式就可以對ui進行操作了呢?這是由於handler總是依附於建立時所在的執行緒,比如我們的handler是在主線程中建立的,而在子執行緒中又無法直接對ui進行操作,於是我們就通過一系列的傳送訊息、入隊、出隊等環節,最後呼叫到了handler的handlemessage()方法中,這時的handlemessage()方法已經是在主線程中執行的,因而我們當然可以在這裡進行ui操作了。

除了傳送訊息之外,我們還有以下幾種方法可以在子執行緒中進行ui操作:

1. handler的post()方法

public class mainactivity extends activity

});

} }).start();

} }

2. view的post()方法

public boolean post(runnable action) else

return handler.post(action);

} 3. activity的runonuithread()方法

public final void runonuithread(runnable action) else

} 4、asynctask

從android3.0開始,系統要求網路訪問必須在子執行緒中進行,否則網路訪問將會失敗並拋networkonmainthreadexception這個異常,這樣做是為了避免主線程由於耗時操作所阻塞從而出現anr現象。

asynctask封裝了執行緒池和handler。asynctask有兩個執行緒池:serialexecutor和thread_pool_executor。前者是用於任務的排隊,預設是序列的執行緒池:後者用於真正的執行任務。asynctask還有乙個handler,叫internalhandler,用於將執行環境從執行緒池切換到主線程。asynctask內部就是通過internalhandler來傳送任務執行的進度以及執行結束等訊息。

asynctask是乙個抽象類,必須要建立乙個子類去繼承它。在繼承時我們可以為asynctask類指定三個泛型引數:

1. params

在執行asynctask時需要傳入的引數,可用於在後台任務中使用。

2. progress

後台任務執行時,如果需要在介面上顯示當前的進度,則使用這裡指定的泛型作為進度單位。

3. result

當任務執行完畢後,如果需要對結果進行返回,則使用這裡指定的泛型作為返回值型別。

重寫的方法有以下四個

1. onpreexecute()

這個方法會在後台任務開始執行之間呼叫,用於進行一些介面上的初始化操作,比如顯示乙個進度條對話方塊等。

2. doinbackground(params…)

這個方法中的所有**都會在子執行緒中執行,我們應該在這裡去處理所有的耗時任務。任務一旦完成就可以通過return語句來將任務的執行結果進行返回,如果asynctask的第三個泛型引數指定的是void,就可以不返回任務執行結果。注意,在這個方法中是不可以進行ui操作的,如果需要更新ui元素,比如說反饋當前任務的執行進度,可以呼叫publishprogress(progress…)方法來完成。

3. onprogressupdate(progress…)

當在後台任務中呼叫了publishprogress(progress…)方法後,這個方法就很快會被呼叫,方法中攜帶的引數就是在後台任務中傳遞過來的。在這個方法中可以對ui進行操作,利用引數中的數值就可以對介面元素進行相應的更新。

4. onpostexecute(result)

當後台任務執行完畢並通過return語句進行返回時,這個方法就很快會被呼叫。返回的資料會作為引數傳遞到此方法中,可以利用返回的資料來進行一些ui操作,比如說提醒任務執行的結果,以及關閉掉進度條對話方塊等。

非同步訊息處理機制

因為android不允許在子執行緒中進行更新ui,非同步訊息處理機制來解決這個問題。android中的非同步訊息處理由4部分組成 message,handler,messagequeue和looper。message 傳遞訊息 handle 傳送,處理資訊 messagequeue 訊息隊裡,存放h...

解析非同步訊息處理機制

android 中的非同步訊息處理主要由四個部分組成,message handler messagequeue 和looper。其中 message 和 handler 在上一小節中我們已經接觸過了,而 messagequeue 和 looper對於你來說還是全新的概念,下面我就對這四個部分進行一下...

android非同步訊息處理機制

我們都知道android的ui更新操作都是在主線程執行的,但是很多時候我們都需要在子執行緒 中執行一些費時的操作,以獲取我們所需要的變更資料。很多剛入門的同學都容易犯的乙個錯誤就是在子執行緒試圖去更新ui控制項,這樣做是被android禁止的,所以會出現崩潰的現象。android的非同步資訊處理機制...