您好,登錄后才能下訂單哦!
本篇文章為大家展示了Android中同步與異步的關系是什么,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
有2方式可以實現:
AsyncTask,Handle
AsyncTask
android提供的簡單用于異步通訊的線程
主要四個實現接口:
onPreExecute(), 該方法將在執行實際的后臺操作前被UI 線程調用。可以在該方法中做一些準備工作,如在界面上顯示一個進度條,或者一些控件的實例化,這個方法可以不用實現。
doInBackground(Params...), 將在onPreExecute 方法執行后馬上執行,該方法運行在后臺線程中。這里將主要負責執行那些很耗時的后臺處理工作。可以調用 publishProgress方法來更新實時的任務進度。該方法是抽象方法,子類必須實現。
onProgressUpdate(Progress...),在publishProgress方法被調用后,UI 線程將調用這個方法從而在界面上展示任務的進展情況,例如通過一個進度條進行展示。
onPostExecute(Result), 在doInBackground 執行完成后,onPostExecute 方法將被UI 線程調用,后臺的計算結果將通過該方法傳遞到UI 線程,并且在界面上展示給用戶.
onCancelled(),在用戶取消線程操作的時候調用。在主線程中調用onCancelled()的時候調用。
調用注意
1) Task的實例必須在UI 線程中創建
2) execute方法必須在UI 線程中調用
3) 不要手動的調用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)這幾個方法,需要在UI線程中實例化這個task來調用。
4) 該task只能被執行一次,否則多次調用時將會出現異常。
5)doInBackground方法返回值和onPostExecute的參數必須對應,這兩個參數在AsyncTask聲明的泛型參數列表中指定,第一個為doInBackground接受的參數,第二個為顯示進度的參數,第第三個為doInBackground返回和onPostExecute傳入的參數。
可以看到這個線程有副線程的接口處理doInBackground,也有UI線程的接口處理onProgressUpdate,在啟動線程時可以傳入泛類參數。
Handler
Handler類可以看做工具類,用來向消息隊列中插入消息的。實例化時自動綁定調用的線程Looper,當處理消息時在該線程中執行。利用這個特性,副線程發送消息,接受消息后在主線程處理,達到主線程和副線程的通訊。
在Android里可以這么理解,因為在android里你可以把UI界面當做主線程,你不能因為下載東西就一直顯示下載,用戶體驗不好,也不被google容許,所以你點擊下載就是開啟子線程去下載了,手機頁面該看什么你就看什么,等下載好子線程就發個message給handler它來更新UI,在你的手機界面顯示或彈出一個下載好了的消息,如果不用handler下載好了你也不知道,還得自己去看。Handler和Thread:子線程是不能更新UI的,所以用Thread開啟子線程后,如果需要更新UI,就通過Handler來更新UI.
而AsyncTask 中:
doInBackground(Params…) 屬于子線程,后臺執行,比較耗時的操作都可以放在這里。注意這里不能直接操作UI。此方法在后臺線程執行,完成任務的主要工作,通常需要較長的時間。在執行過程中可以 調用publicProgress(Progress…)來更新任務的進度。
onPostExecute(Result) 相當于Handler 處理UI的方式,在這里面可以使用在doInBackground 得到的結果處理操作UI。 此方法在主線程執行,任務執行的結果作為此方法的參數返回
looper類是用來封裝消息循環和消息隊列的一個類。
(1) Looper類用來為一個線程開啟一個消息循環。
默認情況下android中新誕生的線程是沒有開啟消息循環的。(主線程除外,主線程系統會自動為其創建Looper對象,開啟消息循環。)
Looper對象通過MessageQueue來存放消息和事件。一個線程只能有一個Looper,對應一個MessageQueue。
(2) 通常是通過Handler對象來與Looper進行交互的。Handler可看做是Looper的一個接口,用來向指定的Looper發送消息及定義處理方法。
默認情況下Handler會與其被定義時所在線程的Looper綁定,比如,Handler在主線程中定義,那么它是與主線程的Looper綁定。
mainHandler = new Handler() 等價于new Handler(Looper.myLooper()).
Looper.myLooper():獲取當前進程的looper對象,類似的 Looper.getMainLooper() 用于獲取主線程的Looper對象。
(3) 在非主線程中直接new Handler() 會報如下的錯誤:
E/AndroidRuntime( 6173): Uncaught handler: thread Thread-8 exiting due to uncaught exception
E/AndroidRuntime( 6173): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
原因是非主線程中默認沒有創建Looper對象,需要先調用Looper.prepare()啟用Looper。
(4) Looper.loop(); 讓Looper開始工作,從消息隊列里取消息,處理消息。
注意:寫在Looper.loop()之后的代碼不會被執行,這個函數內部應該是一個循環,當調用mHandler.getLooper().quit()后,loop才會中止,其后的代碼才能得以運行。
(5) 基于以上知識,可實現主線程給子線程(非主線程)發送消息。
把下面例子中的mHandler聲明成類成員,在主線程通過mHandler發送消息即可。
總結,一般都是綁定主線程的handler,達到通訊目的,在副線程中發送消息。若要創建副線程中綁定handler,則必須先創建副線程的looper,已達到循環發送消息的目的。有兩種方式達到這個目的:
1、通過handler+Looper兩個類。
2、通過HandlerThread這個類,這個是android提供的利用Looper和Handler繼承Thread完成。
上述內容就是Android中同步與異步的關系是什么,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。