Android復習之旅--子線程更新UI

Android4.0版本后耗時的操作(比如請求網絡,下載文件等)不能在UI主線程執行,而且子線程也不能直接更新UI界面。而現實的場景確是子線程在下載文件的同時UI界面能顯示相應的進度信息,既然有了需求,那肯定就會有解決方案。

Android提供了Handler消息機制和AsyncTask抽象類等去實現子線程和UI主線程之間的通信。當然還可以使用Volly,okhttp,Retrofit2.0等第三方開源庫來實現,第三方開源庫使用簡單,功能強大。

but ...,這里只對Handler和AsyncTask進行總結,至于為什么, 我是不會告訴你們是因為我懶的[歐耶]

好了,進入正題 ...


Handler 消息機制

通過Handler消息機制來實現線程間的通信。

那么Handler是什么呢?

Handler 機制主要包括4個關鍵對象,分別是Message、Handler、MessageQueue、Looper。

  • Message 是在線程之間傳遞的消息,它可以在內部攜帶少量的信息,用于在不同的線程之間交換數據
Message msg = new Message();
msg.what = 1;  // 用于攜帶整型數據,區別當前消息
msg.obj = object;  //用于攜帶一個Object對象
//發送消息給Handler
handler.sendMessage(msg);
  • Handler 就是處理者的意思,它主要用于發送消息和處理消息
Handler handler = new Handler(){
      @Override
      public void handleMessage(Message msg) {
          super.handleMessage(msg);
          int what = msg.what;
          Object object = msg.obj;
      }        
};
  • MessageQueue 是消息隊列的意思,它主要用來存放通過Handler發送的消息。通過Handler發送的消息會存在MessageQueue中等待處理,每個線程中有且僅有一個MessageQueue對象。

  • Looper 是每個線程中的MessageQueue的管家,它主要進行消息循環,一旦發現MessageQueue中存在消息,就會把它取出并傳遞到Handler的handlerMessage()方法中(如果MessageQueue中不存在消息,Looper會自動阻塞,相當于wait(); 而如果Handler發送了一個消息,Looper就會被喚醒),每個線程有且僅有一個Looper。

引用 Carson_Ho Handler在創建的時候可以顯示指定Looper,這樣在Handler在調用sendMessage()投遞消息的時候會將消息添加到指定的Looper里面的MessageQueue。如果不指定Looper,Handler默認綁定的是創建它的線程的Looper。一般默認即可。


AsyncTask 抽象類

為了可以在子線程中更好地對UI進行操作,Android提供了一個很好用地工具類--AsyncTask。使用AsyncTask可以非常簡單地從子線程切換到主線程,它的原理是基于異步消息處理機制的。

class DownLoadTask extends AsyncTask<Void, Integer, Boolean> {
    // 1. 預加載,運行在主線程
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }
    // 2. 正在加載,運行在子線程(主要方法)
    @Override
    protected Boolean doInBackground(Void... params) {
        return false;
    }
    // 3. 更新進度的方法,運行在主線程
    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
    }
    // 4. 加載結束,運行在主線程(主要方法)
    @Override
    protected void onPostExecute(Boolean result){
        super.onPostExecute(result);
    }
}

其中,
第一個泛型參數(對應doInBackground里的參數類型 ):在執行AsyncTask時需要傳入的參數,用于后臺任務中使用;
第二個泛型參數(對應onProgressUpdate里的參數類型):在后臺任務執行時,如果需要在界面上顯示當前的進度,則使用該參數作為進度單位;
第三個泛型參數(對應onPostExecute里的參數類型和doInBackground的返回類型):當任務執行完畢后,如果需要對結果進行返回,則使用該參數作為返回值類型。


希望對你們有所幫助

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容