Android Handler機制理解和AsyncTask使用小記

蘆葦科技App技術團隊發表於2019-03-01

Android Handler機制理解和AsyncTask使用小記

這是一篇淺入淺出的文章,對handler的使用和問題進行了一個總結,推薦看文章的你自己動手去練習,記憶和理解會更深刻一點。

  1. Handler的概念

我們先看一下Handler的百科介紹:

Handler主要用於非同步訊息的處理:當發出一個訊息之後,首先進入一個訊息佇列,傳送訊息的函式即刻返回,而另外一個部分在訊息佇列中逐一將訊息取出,
然後對訊息進行處理,也就是傳送訊息和接收訊息不是同步的處理。 這種機制通常用來處理相對耗時比較長的操作。 
複製程式碼

比較難明白,我們先將概念拆分開理解,放下前面關於訊息的部分,先著重看最後一句:處理相對耗時較長的操作。

在Android中,主執行緒中不能執行耗時操作,不然可能會造成ANR等問題,只能在子執行緒來進行。比如需要下載一個圖片並顯示到介面上,那麼直接按照邏輯,下載圖片是可能耗時的操作,新建一個執行緒執行下載,然後將下載的圖片傳入介面對應的檢視中,程式碼如下:

new Thread(){
    @Override
    public void run() {
        super.run();
        final Bitmap bitmap = downloadImg();//下載圖片,返回bitmap
        ivImg.setImageBitmap(bitmap);//傳入下載的圖片到檢視
    }
};
複製程式碼

邏輯是正確的,但操作不對,程式無法執行。

因為在Android中,只有主執行緒能更新UI,所以主執行緒也叫UI執行緒,子執行緒中是不能更新UI的。這時候我們就可以用到Handler了,Handler可以作為Android更新UI的一套機制,正確的操作程式碼如下:

Handler handler = new Handler(); 
new Thread(){
    @Override
    public void run() {
        super.run();
        final Bitmap bitmap = downloadImg();//下載圖片,返回bitmap
        handler.post(new Runnable() {
            @Override
            public void run() {
                ivImg.setImageBitmap(bitmap);//通過Handler通知主執行緒更新UI
            }
        })
    }
};
複製程式碼

可以看到,UI的操作放被到了Runnable物件中,然後利用Handler.post(Runnable)實現了UI的更新,可以簡單理解Handler為一個傳信者,將子執行緒中需要更新UI的資訊傳入主執行緒中進行。

這是Handler的一種使用方法,通過post(Runnable),第二種是sendMessage()方式,示例如下:

mHandler = new Handler(new Handler.Callback() {
    @Override
    public boolean handleMessage(Message msg) {
        if(msg==1){
            tvText.setText("接收到訊息,更改UI");//通過Handler通知主執行緒更新UI
        }
        return false;
    }
});
new Thread() {
    @Override
    public void run() {
        super.run()
        Message msg = new Message();
        msg.what = 1;
        mHandler.sendMessage(msg);
    }
}.start();
複製程式碼

這裡可以看到,Handler實現了訊息的傳出、訊息的接收與處理,其實在post(Runnable)方法中,Runnable物件本身也是作為一個訊息傳出的,再次回顧Handler的概念:

Handler主要用於非同步訊息的處理:當發出一個訊息之後,首先進入一個訊息佇列,傳送訊息的函式即刻返回,而另外一個部分在訊息佇列中逐一將訊息取出,
然後對訊息進行處理,也就是傳送訊息和接收訊息不是同步的處理。 這種機制通常用來處理相對耗時比較長的操作。 
複製程式碼

我們知道了Handler是一個關於訊息非同步處理的任務機制,對於非同步和同步,舉個例子說明

  • 同步處理:買傢俱→在商場選擇好傢俱→等待工人裝車→送到家中安裝傢俱→處理其他事物
  • 非同步處理:買傢俱→在網上買好傢俱→等待過程中處理其他事物→傢俱送到安裝傢俱

可以看出,非同步操作最大的特點是,不會阻礙呼叫者的工作,無需等待前一個操作做完才做下一個操作,對於耗時的操作,使用非同步來處理是非常有必要的。

那麼在進行非同步操作的過程中,需要一個訊息的傳遞者來指導各部分進行操作,在剛才網購的例子裡,這個傳遞者是網上商城,而在Android的UI處理中,這個訊息傳遞者就是Handler。

其他一些Handler的使用方法

  • handler.post()
  • handler.postDelayed()
  • handler.sendMessage();
  • handler.sendEmptyMessage();
  • handler.removeCallback(runnable)
  1. AsyncTask非同步任務的使用

    前面介紹了Handler+Thread進行非同步訊息處理,Android對此有封裝一個更好用的元件——AsyncTask。原理是相同的,但相比Handler+Thread更加簡單易用。

    使用時首先需要構建AsyncTask子類的泛型引數,AsyncTask<Params,Progress,Result>是一個抽象類,通常用於被繼承,繼承AsyncTask需要指定如下三個泛型引數:

    • Params:啟動任務時輸入的引數型別.
    • Progress:後臺任務執行中返回進度值的型別.
    • Result:後臺任務執行完成後返回結果的型別.

    在構建AsyncTask子類主要有如下幾個回撥方法:

    • doInBackground:必須重寫,非同步執行後臺執行緒要完成的任務,耗時操作將在此方法中完成.
    • onPreExecute:執行後臺耗時操作前被呼叫,通常用於進行初始化操作.
    • onPostExecute:當doInBackground方法完成後,系統將自動呼叫此方法,並將doInBackground方法返回的值傳入此方法.通過此方法進行UI的更新.
    • onProgressUpdate:當在doInBackground方法中呼叫publishProgress方法更新任務執行進度後,將呼叫此方法.通過此方法我們可以知曉任務的完成進度.

相關文章