Android4.0版本後耗時的操做(好比請求網絡,下載文件等)不能在UI主線程執行,並且子線程也不能直接更新UI界面。而現實的場景確是子線程在下載文件的同時UI界面能顯示相應的進度信息,既然有了需求,那確定就會有解決方案。javascript
Android提供了Handler消息機制和AsyncTask抽象類等去實現子線程和UI主線程之間的通訊。固然還可使用Volly,okhttp,Retrofit2.0等第三方開源庫來實現,第三方開源庫使用簡單,功能強大。java
but ...,這裏只對Handler和AsyncTask進行總結,至於爲何, 我是不會告訴大家是由於我懶的[歐耶]網絡
好了,進入正題 ...異步
經過Handler消息機制來實現線程間的通訊。async
那麼Handler是什麼呢?ide
Handler 機制主要包括4個關鍵對象,分別是Message、Handler、MessageQueue、Looper。工具
Message msg = new Message();
msg.what = 1; // 用於攜帶整型數據,區別當前消息
msg.obj = object; //用於攜帶一個Object對象
//發送消息給Handler
handler.sendMessage(msg);複製代碼
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對象。oop
Looper 是每一個線程中的MessageQueue的管家,它主要進行消息循環,一旦發現MessageQueue中存在消息,就會把它取出並傳遞到Handler的handlerMessage()方法中(若是MessageQueue中不存在消息,Looper會自動阻塞,至關於wait(); 而若是Handler發送了一個消息,Looper就會被喚醒),每一個線程有且僅有一個Looper。ui
引用 Carson_Ho Handler在建立的時候能夠顯示指定Looper,這樣在Handler在調用sendMessage()投遞消息的時候會將消息添加到指定的Looper裏面的MessageQueue。若是不指定Looper,Handler默認綁定的是建立它的線程的Looper。通常默認便可。spa
爲了能夠在子線程中更好地對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的返回類型):當任務執行完畢後,若是須要對結果進行返回,則使用該參數做爲返回值類型。
但願對大家有所幫助