關(guān)于AsyncTask 你必須要了解的一些事情
大家都知道,在子線程中是不能更新UI的,必須要采用異步消息處理機(jī)制。一般的做法就是在有需要的地方,使用Handler發(fā)送消息給主線程,然后在主線程中處理消息更新UI。如果好多子線程都有更新UI的需求,那么場(chǎng)面就有點(diǎn)難以控制了,大家必須在代碼中手動(dòng)處理Handler的消息請(qǐng)求。這樣子問題顯然會(huì)復(fù)雜很多。其實(shí)這樣子的情況android已經(jīng)為我們考慮到了。AsyncTask就是天生被android設(shè)計(jì)出來(lái)為我們解決這樣子的問題的。其實(shí)翻看源碼,就會(huì)知道AsyncTask的底層封裝的仍然是android的Handler消息處理機(jī)制。下面的幾篇文章就來(lái)詳細(xì)的學(xué)習(xí)什么是AsyncTask,以及它是如何做的。
一、AsyncTask是什么
AsyncTask是android給我們封裝的一套異步消息處理工具。使用這個(gè)工具,可以讓異步消息的處理變得更加的簡(jiǎn)單,開發(fā)者避免了很多的麻煩。也就是說AsyncTak天生用來(lái)被設(shè)計(jì)做兩件事:
(1)子線程中更新UI
(2)異步加載數(shù)據(jù)
下面來(lái)學(xué)習(xí)一下關(guān)于它的最基礎(chǔ)的知識(shí)。
首先AsyncTask是一個(gè)抽象類,必須要?jiǎng)?chuàng)建它的子類。但是在繼承AsyncTask類的時(shí)候,需要指定三個(gè)泛型參數(shù)。解釋分別如下:
- (1)Params
- 在執(zhí)行AsyncTask時(shí)需要傳入的參數(shù),可用于在后臺(tái)任務(wù)中使用。
- (2)Progress
- 后臺(tái)任務(wù)在執(zhí)行時(shí),如果需要在界面上顯示當(dāng)前進(jìn)度,則就用Progress指定的泛型作為進(jìn)度單位。
- (3)Result
- 當(dāng)后臺(tái)任務(wù)執(zhí)行完畢后,如果需要對(duì)結(jié)果進(jìn)行返回,那么就用這里指定的泛型作為返回的類型。
然后一般在子類中,需要重寫下面的幾個(gè)回調(diào)方法,他們都是自動(dòng)被調(diào)用的,不要在代碼中人工調(diào)用。
- (1)onPreExexute()
- 該方法在后臺(tái)任務(wù)執(zhí)行前,即doInBackground方法執(zhí)行前被調(diào)用。通常在這里執(zhí)行一些初始化的操作,比如顯示一個(gè)進(jìn)度條。
- (2)doInBackground(Params...)
- 該方法用來(lái)執(zhí)行后臺(tái)任務(wù),它的所有代碼都是在子線程中操作,任務(wù)一旦完成就會(huì)用return來(lái)返回結(jié)果。當(dāng)然它的參數(shù)和返回結(jié)果的類型就是上面我們所指定的Params和Result。千萬(wàn)注意,不要在這個(gè)
- 方法中執(zhí)行更新UI的操作。如果需要更新UI元素,比如說反饋當(dāng)前任務(wù)的進(jìn)度,可以調(diào)用publishProgress(Progress...)方法來(lái)完成。
- (3)onProgressUpdate(Progress...)
- 當(dāng)在后臺(tái)任務(wù)中調(diào)用了publishProgress方法后,就會(huì)自動(dòng)調(diào)用該方法,方法中的參數(shù)就是publishProgress方法傳遞過來(lái)的。這個(gè)方法可以對(duì)UI進(jìn)行更新。
- (4)onPostExecute(Result)
- 當(dāng)后臺(tái)任務(wù)執(zhí)行完畢,即doInBackground執(zhí)行完畢后,該方法被調(diào)用。doInBackground返回的結(jié)果就是該方法的參數(shù),這這里可以執(zhí)行任務(wù)完成后的邏輯,比如說關(guān)閉一個(gè)進(jìn)度條,更新一些UI等。
需要說明的是這幾個(gè)方法,只有doInBackground方法是在子線程中執(zhí)行的,其他的都是在主線程中執(zhí)行的。那么啟動(dòng)和取消這個(gè)任務(wù)的方法是什么呢?如下:
- myAsyncTask.execute() 其中該任務(wù)
- yAsyncTask.cancel() 取消該任務(wù)
好了,了解到上面的基礎(chǔ)知識(shí)后,我們來(lái)做一個(gè)小練習(xí),加深一下印象。
二、一個(gè)實(shí)際練習(xí)
我們來(lái)編寫出一個(gè)AsynTask子類,實(shí)際運(yùn)行一下吧。新建項(xiàng)目,然后新建子類繼承自AsynTask,代碼如下:
- 1 package com.example.asynctasktest;
- 2
- 3 import android.os.AsyncTask;
- 4 import android.util.Log;
- 5
- 6
- 7
- 8 public class MyAsyncTask extends AsyncTask<Void, Void, Void>{
- 9
- 10
- 11
- 12 protected Void doInBackground(Void... params) {
- 13 Log.d("付勇焜----->","doInBackground");
- publishProgress();
- 14 return null;
- 15 }
- 16
- 17
- 18 protected void onPreExecute() {
- 19 Log.d("付勇焜----->","onPreExecute");
- 20 super.onPreExecute();
- 21 }
- 22
- 23
- 24 protected void onPostExecute(Void result) {
- 25 Log.d("付勇焜----->","onPostExecute");
- 26 super.onPostExecute(result);
- 27 }
- 28
- 29
- 30 protected void onProgressUpdate(Void... values) {
- 31 Log.d("付勇焜----->","onProgressUpdate");
- 32 super.onProgressUpdate(values);
- 33 }
- 34
- 35
- 36
- 37 }
我們編寫了一個(gè)最簡(jiǎn)單的AsyncTask子類,傳入的參數(shù)都是空值, 然后在每一個(gè)方法中都打印出一句話,主要是為了便于觀察他們的執(zhí)行順序。
然后我們?cè)傩薷腗ainActivity的代碼,如下:
- 1 package com.example.asynctasktest;
- 2
- 3 import android.os.Bundle;
- 4 import android.app.Activity;
- 5
- 6
- 7 public class MainActivity extends Activity {
- 8
- 9
- 10 protected void onCreate(Bundle savedInstanceState) {
- 11 super.onCreate(savedInstanceState);
- 12 setContentView(R.layout.activity_main);
- 13
- 14 MyAsyncTask mTask = new MyAsyncTask();
- 15 mTask.execute();
- 16 }
- 17
- 18 }
然后運(yùn)行程序,打印結(jié)果如下:
從打印的結(jié)果很容易就看出方法的執(zhí)行順序了吧。如下:
onPreExecute------>onProgressUpdate(調(diào)用了publishProgress方法才會(huì)調(diào)用該方法)------->doInBackground--------->onPostExecute
好了,本篇文章帶你大致了解了一下AsynTask的基礎(chǔ)知識(shí),那么在下一篇文章中,就一起來(lái)做一個(gè)實(shí)際例子吧,熟練使用AsynTask這套機(jī)制!