《Android》『Multi – Threads』- 實現多執行緒的三種方式 (Post、Handler、AsyncTask)

《Android Developers 參考文獻》

➥Handler

➥AsyncTask

 

《簡單介紹》

在撰寫 Android 程式的過程中,常常會碰到一些需要快速更新 UI 介面的功能需求,這時候如果我們直接將更新 UI 的程式寫在主執行緒上,會發現 UI 一動也不動,直到所有運算處理完,才顯示最後的 UI 變動結果,若是運算的量再稍微大一點,甚至會產生 ANR(Application is Not Responding) 的對話框。

這是因為主執行緒會優先處理邏輯運算的關係,但是也只有主執行緒才能更新 UI,因此為了不讓畫面卡住,在處理這種需要大量更新 UI 的需求的時候,我們通常會透過新增子執行緒的方式來處理邏輯運算,並在處理完成的不同階段,再通知主執行緒更新 UI,避免程式出問題。

 

《程式範例》

這邊直接透過程式碼片段,來說明實現多執行緒的幾種方式。

main_activity.xml

首先我們先定義了一個包含五個按鈕的介面,分別代表不同的執行緒實作方式。

MainActivity.java

接著在 MainActivity 中,針對不同按鈕實作程式碼,相關說明如下 –

1. 在 onANRClick() 中,由於直接在主執行緒、也就是 UI 執行緒上做更新 tvANR 元件畫面的操作,主執行緒永遠卡在 While 的邏輯運算裡,邏輯運算無法結束,便無法更新 UI,最終導致 ANR 的結果。

2. 在 onUiThreadClick() 中,新增了一個子執行緒來執行邏輯運算並在更新 UI 畫面,此按鈕按下後程式會直接 Crash,因為在 Android 中,只有主執行緒可以更新 UI 畫面。

3. 在 onViewPostClick() 中,我們同樣新增一個子執行緒來執行邏輯運算,但在更新 UI 畫面的部分,我們透過 tvViewPost.post(new Runnable(){…}) 的方式,將其導回主執行緒來處理,在 post 方法中,其更新畫面的順序是先進先出,另外我們額外定義了 Thread.sleep(100) 的延遲,用以防止 UI 更新過快。

4. 在 onHandlerClick() 中,我們用到了兩個自訂的類別,分別是 MyHandlerWorkThread,MyHandler 透過建構子將需要更新 UI 介面的元件代入,並在其 handleMessage 中定義好接收到不同參數時所要執行的動作,WorkThread 則是一個繼承自 Thread 的自訂類別,在其中透過建構子將 MyHandler 物件傳入,再藉由 handler.obtainMessage(…) 的方式,來觸發 MyHandler 物件中的 handleMessage(),相關程式碼如下 :

MyHandler.java

WorkThread.java

在這類別中,我們透過 handler.obtainMessage(int work, int arg1, int arg2, object obj) 方法,分別傳遞所需的資訊去觸發 MyHandler 中的 handleMessage 函式,其中第一個參數的意義代表要做什麼,第二至四個參數代表所可以夾帶的資訊,帶有一個 object 型別的參數以傳遞任何資料,這邊我們自訂了 Common 類別的參數來設定不同的執行內容,關於 Common 類別的定義如下。

Common.java

5. 在 onAsyncTaskClick() 中,我們透過繼承 AsyncTask<Integer, Integer, String> 自訂了一個 MyAsyncTask 類別,其中附帶的三個參數(Integer, Integer, String),分別對應到三個名為 doInBackground()、onProgressUpdate()、onPostExecute() 的 override 方法之傳入參數,透過 AsyncTask 本身的架構,我們可以定義在 Thread 執行前、執行期間以及執行完成後,該做些甚麼事。

其中要注意的是,myAsyncTask.execute(100) 方法代表將會傳入一個值為 100 的參數給 doInBackground() 所代入的參數,此參數可以不只一個, publishProgress(i) 會自動呼叫 onProgressUpdate() 方法,並將 i 參數代入,在 doInBackground() 中最後 return 的值,亦會自動代入 onPostExecute() 的參數並呼叫。

賽肥膩膩

我們是低調到不行的肥膩夫妻檔,一路上一邊吵鬧一邊記錄著生活大小事,最近迷上了宅在家追劇,希望能透過文字將所有看過的影集好好紀錄,整理成屬於我們自己的回憶資料庫。

上 / 下一篇文章

臉書留言

一般留言

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *