AsyncTask 異步任務,主要包含兩個關鍵類:
InternalHandler:消息處理器, 用於處理線程之間消息.
ThreadPoolExecutor:線程池, 用於處理耗時任務
1、onPreExecute(): 在UI線程裏面調用,它在這個task執行後會立即調用。我們在這個方法裏面通常是用於建立一個任務,比如顯示一個等待對話框來通知用戶。
2、doInBackground(Params...):這個方法從名字就可以看出,它是運行在後臺線程的,在這個方法裏面,去做耗時的事情,比如下載訪問網絡,操作文件等。
這這個方法裏面,我們可以調用publishProgress(Progress...)來調用當前任務的進度,調用了這個方法後,對應的onProgressUpdate(Progress...)方法會被調用,
這個方法是運行在UI線程的。
3、onProgressUpdate(Progress...):運行在UI線程,在調用publishProgress()方法之後。這個方法用來在UI上顯示任何形式的進度,比如你可以顯示一個等待對話框,
也可以顯示一個文本形式的log,還可以顯示toast對話框。
4、onPostExecute(Result):當task結束後調用,它運行在UI線程。
5、取消一個task,我們可以在任何時候調用cancel(Boolean)來取消一個任務,當調用了cancel()方法後,onCancelled(Object)方法就會被調用,
onPostExecute(Object)方法不會被調用,在doInBackground(Object[])方法中,我們可以用isCancelled()方法來檢查任務是否取消。
6、幾點規則:
AsyncTask實例必須在UI線程中創建
execute(Params...)方法必須在UI線程中調用。
不用手動調用onPreExecute(), onPostExecute(), doInBackground(), onProgressUpdate()方法。
一個任務只能被執行一次
------------------------------------
# AsyncTask原理
new AsyncTask<String, String, String>() {
// 2. 運行在主線程中, 做一些準備操作.
public void onPreExecute() {
}
// 3. 運行在子線程中, 做一些耗時的任務.
public String doInBackground(String... params) {
return null;
}
// 4. 運行主線程中, result就是doInBackground方法返回的值. 做一些收尾操作.
public void onPostExecute(String result) {
}
}.execute(String... params);
// 1. 開始執行異步任務.
> #### AsyncTask的execute的方法, 代碼如下:
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
...
mStatus = Status.RUNNING;
// 調用用戶的實現方法, 讓用戶做一些準備操作. 運行在主線程中.
onPreExecute();
// 把mWorker中的mParams賦值爲用戶傳遞進來的參數.
mWorker.mParams = params;
// 使用線程池, 執行任務. 這時進入到子線程中.
sExecutor.execute(mFuture);
return this;
}
> #### 查看mWorker的初始化過程, 代碼如下:
// AsyncTask構造函數在一開始使用異步任務時, 已經調用.
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
...
}
};
// 1. 把mWorker對象傳遞給了FutureTask的構造函數
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
...
}
};
}
// FutureTask類中接收的是Callable的類型, 其實WorkerRunnable類型實現了Callable的類型.
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
// 2. 把callable(mWorker)傳遞給了Sync的構造函數.
sync = new Sync(callable);
}
Sync(Callable<V> callable) {
// 3. 把接收過來的callable(mWorker)對象賦值給Sync類中的成員變量callable
// 總結: Sync類中的成員變量callable就是AsyncTask中的mWorker對象.
this.callable = callable;
}
> #### mFuture對象中的run方法如下:
public void run() {
// 1. 調用了innerRun方法.
sync.innerRun();
}
void innerRun() {
if (!compareAndSetState(READY, RUNNING))
return;
runner = Thread.currentThread();
if (getState() == RUNNING) { // recheck after setting thread
V result;
try {
// 2. 調用了callable(mWorker)的call方法. 獲取一個返回結果.
result = callable.call();
} catch (Throwable ex) {
setException(ex);
return;
}
// 4. 把結果傳遞給set方法.
set(result);
} else {
releaseShared(0); // cancel
}
}
// 在AsyncTask的構造函數中, mWorker對象初始化時, 已經覆蓋了call方法, 代碼如下
public Result call() throws Exception {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
// 3. 調用了用戶實現的doInBackground方法, 去執行一個耗時的任務. 運行在子線程中.
// doInBackground接收的參數就是execute方法接收的參數.
return doInBackground(mParams);
}
----------
protected void set(V v) {
// 5. 繼續把參數傳遞給innerSet方法.
sync.innerSet(v);
}
void innerSet(V v) {
for (;;) {
int s = getState();
if (s == RAN)
return;
if (s == CANCELLED) {
// aggressively release to set runner to null,
// in case we are racing with a cancel request
// that will try to interrupt runner
releaseShared(0);
return;
}
if (compareAndSetState(s, RAN)) {
// 6. 把doInBackground返回的結果賦值給成員變量result
result = v;
releaseShared(0);
// 7. 調用FutureTask中的done方法.
done();
return;
}
}
}
----------
// 此方法定義在AsyncTask的構造函數中, 初始化mFuture時,已經覆蓋了done方法, 代碼如下:
@Override
protected void done() {
Message message;
Result result = null;
try {
// 8. 調用FutureTask中的get方法獲取result(doInBackground返回的結果).
result = get();
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occured while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
message = sHandler.obtainMessage(MESSAGE_POST_CANCEL,
new AsyncTaskResult<Result>(AsyncTask.this, (Result[]) null));
message.sendToTarget();
return;
} catch (Throwable t) {
throw new RuntimeException("An error occured while executing "
+ "doInBackground()", t);
}
// 11. 創建一個消息對象.
// msg.what = MESSAGE_POST_RESULT;
// msg.obj = new AsyncTaskResult<Result>(AsyncTask.this, result);
message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(AsyncTask.this, result));
// 12. 把當前消息使用sHandler發送出去.
message.sendToTarget();
}
public V get() throws InterruptedException, ExecutionException {
// 9. 轉調innerGet方法.
return sync.innerGet();
}
V innerGet() throws InterruptedException, ExecutionException {
...
// 10. 把result(doInBackground的結果)返回回去. result成員變量是在innerSet方法中賦值. 詳情看第6步.
return result;
}
----------
private static class InternalHandler extends Handler {
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
public void handleMessage(Message msg) {
// 把obj轉換成AsyncTaskResult類, 這個類中mTask對象就是當前的AsyncTask對象. mData對象就是doInBackground的返回結果.
AsyncTaskResult result = (AsyncTaskResult) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
// There is only one result
// 13. 調用AsyncTask中的finish方法, 並且把doInBackground的返回結果傳遞進去.
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
case MESSAGE_POST_CANCEL:
result.mTask.onCancelled();
break;
}
}
}
private void finish(Result result) {
if (isCancelled()) result = null;
// 14. 把doInBackground的返回結果傳遞給用戶實現的onPostExecute方法. 運行在主線程中, 用戶可以做一些操作界面, 更新界面的操作.
onPostExecute(result);
mStatus = Status.FINISHED;
}