Android4.0版本后耗時(shí)的操作(比如請求網(wǎng)絡(luò),下載文件等)不能在UI主線程執(zhí)行传于,而且子線程也不能直接更新UI界面。而現(xiàn)實(shí)的場景確是子線程在下載文件的同時(shí)UI界面能顯示相應(yīng)的進(jìn)度信息醉顽,既然有了需求沼溜,那肯定就會(huì)有解決方案。
Android提供了Handler消息機(jī)制和AsyncTask抽象類等去實(shí)現(xiàn)子線程和UI主線程之間的通信游添。當(dāng)然還可以使用Volly系草,okhttp,Retrofit2.0等第三方開源庫來實(shí)現(xiàn)唆涝,第三方開源庫使用簡單找都,功能強(qiáng)大。
but ...廊酣,這里只對Handler和AsyncTask進(jìn)行總結(jié)能耻,至于為什么, 我是不會(huì)告訴你們是因?yàn)槲覒械腫歐耶]
好了亡驰,進(jìn)入正題 ...
Handler 消息機(jī)制
通過Handler消息機(jī)制來實(shí)現(xiàn)線程間的通信晓猛。
那么Handler是什么呢?
Handler 機(jī)制主要包括4個(gè)關(guān)鍵對象隐解,分別是Message鞍帝、Handler、MessageQueue煞茫、Looper帕涌。
- Message 是在線程之間傳遞的消息,它可以在內(nèi)部攜帶少量的信息续徽,用于在不同的線程之間交換數(shù)據(jù)
Message msg = new Message();
msg.what = 1; // 用于攜帶整型數(shù)據(jù)蚓曼,區(qū)別當(dāng)前消息
msg.obj = object; //用于攜帶一個(gè)Object對象
//發(fā)送消息給Handler
handler.sendMessage(msg);
- Handler 就是處理者的意思,它主要用于發(fā)送消息和處理消息
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
int what = msg.what;
Object object = msg.obj;
}
};
MessageQueue 是消息隊(duì)列的意思钦扭,它主要用來存放通過Handler發(fā)送的消息纫版。通過Handler發(fā)送的消息會(huì)存在MessageQueue中等待處理,每個(gè)線程中有且僅有一個(gè)MessageQueue對象客情。
Looper 是每個(gè)線程中的MessageQueue的管家其弊,它主要進(jìn)行消息循環(huán),一旦發(fā)現(xiàn)MessageQueue中存在消息膀斋,就會(huì)把它取出并傳遞到Handler的handlerMessage()方法中(如果MessageQueue中不存在消息梭伐,Looper會(huì)自動(dòng)阻塞,相當(dāng)于wait(); 而如果Handler發(fā)送了一個(gè)消息仰担,Looper就會(huì)被喚醒)糊识,每個(gè)線程有且僅有一個(gè)Looper。
引用 Carson_Ho Handler在創(chuàng)建的時(shí)候可以顯示指定Looper,這樣在Handler在調(diào)用sendMessage()投遞消息的時(shí)候會(huì)將消息添加到指定的Looper里面的MessageQueue赂苗。如果不指定Looper愉耙,Handler默認(rèn)綁定的是創(chuàng)建它的線程的Looper。一般默認(rèn)即可拌滋。
AsyncTask 抽象類
為了可以在子線程中更好地對UI進(jìn)行操作朴沿,Android提供了一個(gè)很好用地工具類--AsyncTask。使用AsyncTask可以非常簡單地從子線程切換到主線程鸠真,它的原理是基于異步消息處理機(jī)制的悯仙。
class DownLoadTask extends AsyncTask<Void, Integer, Boolean> {
// 1. 預(yù)加載龄毡,運(yùn)行在主線程
@Override
protected void onPreExecute() {
super.onPreExecute();
}
// 2. 正在加載吠卷,運(yùn)行在子線程(主要方法)
@Override
protected Boolean doInBackground(Void... params) {
return false;
}
// 3. 更新進(jìn)度的方法,運(yùn)行在主線程
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
// 4. 加載結(jié)束沦零,運(yùn)行在主線程(主要方法)
@Override
protected void onPostExecute(Boolean result){
super.onPostExecute(result);
}
}
其中祭隔,
第一個(gè)泛型參數(shù)(對應(yīng)doInBackground里的參數(shù)類型 ):在執(zhí)行AsyncTask時(shí)需要傳入的參數(shù),用于后臺(tái)任務(wù)中使用路操;
第二個(gè)泛型參數(shù)(對應(yīng)onProgressUpdate里的參數(shù)類型):在后臺(tái)任務(wù)執(zhí)行時(shí)疾渴,如果需要在界面上顯示當(dāng)前的進(jìn)度,則使用該參數(shù)作為進(jìn)度單位屯仗;
第三個(gè)泛型參數(shù)(對應(yīng)onPostExecute里的參數(shù)類型和doInBackground的返回類型):當(dāng)任務(wù)執(zhí)行完畢后搞坝,如果需要對結(jié)果進(jìn)行返回,則使用該參數(shù)作為返回值類型魁袜。
希望對你們有所幫助