淺談Android中AsyncTask的工作原理
概述
實(shí)際上,AsyncTask內(nèi)部是封裝了Thread和Handler。雖然AsyncTask很方便的執(zhí)行后臺(tái)任務(wù),以及在主線(xiàn)程上更新UI,但是,AsyncTask并不合適進(jìn)行特別耗時(shí)的后臺(tái)操作,對(duì)于特別耗時(shí)的任務(wù),個(gè)人還是建議使用線(xiàn)程池。好了,話(huà)不多說(shuō)了,我們先看看AsyncTask的簡(jiǎn)單用法吧。
AsyncTask使用方法
AsyncTask是一個(gè)抽象的泛型類(lèi)。簡(jiǎn)單的介紹一下它的使用方式代碼如下:
package com.example.huangjialin.myapplication;
import android.os.AsyncTask;
import android.util.Log;
public class AsyncTaskTest extends AsyncTask<String, Object, Long>{
@Override
protected void onPreExecute() {
super.onPreExecute();
Log.i("AsyncTaskTest","---準(zhǔn)備下載---");
}
@Override
protected Long doInBackground(String... params) {
Log.i("AsyncTaskTest","---在后臺(tái)正在下載---");
return null;
}
@Override
protected void onProgressUpdate(Object... values) {
super.onProgressUpdate(values);
Log.i("AsyncTaskTest","---在更新---");
}
@Override
protected void onPostExecute(Long aLong) {
super.onPostExecute(aLong);
Log.i("AsyncTaskTest","---下載完成,將結(jié)果返回到主線(xiàn)程--");
}
}
然后在activity中調(diào)用 new AsyncTaskTest().execute();就可以了...使用起來(lái)比較簡(jiǎn)單,這里就不在講述怎么使用了。
AsyncTask的4個(gè)核心方法
1、onPreExecute():該方法在主線(xiàn)程中執(zhí)行,在執(zhí)行異步任務(wù)之前會(huì)被調(diào)用,一般用于一些準(zhǔn)備工作。
2、doInBackground(String... params):這個(gè)方法是在線(xiàn)程池中執(zhí)行,此方法用于執(zhí)行異步任務(wù)。在這個(gè)方法中可以通過(guò)publishProgress方法來(lái)更新任務(wù)的進(jìn)度,publishProgress方法會(huì)調(diào)用onProgressUpdate方法,另外,任務(wù)的結(jié)果返回給onPostExecute方法。
3、onProgressUpdate(Object... values):該方法在主線(xiàn)程中執(zhí)行,主要用于任務(wù)進(jìn)度更新的時(shí)候,該方法會(huì)被調(diào)用。
4、onPostExecute(Long aLong):在主線(xiàn)程中執(zhí)行,在異步任務(wù)執(zhí)行完畢之后,該方法會(huì)被調(diào)用,該方法的參數(shù)及為后臺(tái)的返回結(jié)果。
除了這幾個(gè)方法之外還有一些不太常用的方法,如onCancelled(),在異步任務(wù)取消的情況下,該方法會(huì)被調(diào)用。
好了,AsyncTask基本的使用就介紹到這里,下面我們進(jìn)入主題,我們一起看看AsyncTask的工作原理。
AsyncTask的工作原理
先從execute走起,源碼來(lái)了
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
@MainThread
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
if (mStatus != Status.PENDING) {
switch (mStatus) {
case RUNNING:
throw new IllegalStateException("Cannot execute task:"
+ " the task is already running.");
case FINISHED:
throw new IllegalStateException("Cannot execute task:"
+ " the task has already been executed "
+ "(a task can be executed only once)");
}
}
mStatus = Status.RUNNING;
onPreExecute();
mWorker.mParams = params;
exec.execute(mFuture);
return this;
}
為了方面分析,我就把英文注釋干掉了…源碼可以知道從上面的execute方法內(nèi)部調(diào)用的是executeOnExecutor()方法。而sDefaultExecutor實(shí)際上是一個(gè)串行的線(xiàn)程池。而onPreExecute()方法在這里就會(huì)被調(diào)用了。接著看這個(gè)線(xiàn)程池。
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Result result = null;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
postResult(result);
}
return result;
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
try {
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occurred while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
}
從上面的代碼可以知道,AsyncTask的執(zhí)行是排隊(duì)執(zhí)行的,因?yàn)橛嘘P(guān)鍵字synchronized,而AsyncTask的Params參數(shù)就封裝成為FutureTask類(lèi),F(xiàn)utureTask這個(gè)類(lèi)是一個(gè)并發(fā)類(lèi),在這里它充當(dāng)了Runnable的作用。接著FutureTask會(huì)交給SerialExecutor的execute方法去處理,而SerialExecutor的executor方法首先就會(huì)將FutureTask添加到mTasks隊(duì)列中,如果這個(gè)時(shí)候沒(méi)有任務(wù),就會(huì)調(diào)用scheduleNext()方法,執(zhí)行下一個(gè)任務(wù)。如果有任務(wù)的話(huà),則執(zhí)行完畢后最后在調(diào)用 scheduleNext();執(zhí)行下一個(gè)任務(wù)。直到所有任務(wù)被執(zhí)行完畢。而AsyncTask的構(gòu)造方法中有一個(gè)call()方法,而這個(gè)方法由于會(huì)被FutureTask的run方法執(zhí)行。所以最終這個(gè)call方法會(huì)在線(xiàn)程池中執(zhí)行。而doInBackground這個(gè)方法就是在這里被調(diào)用的。我們好好研究一下這個(gè)call()方法。
public Result call() throws Exception {
mTaskInvoked.set(true);
Result result = null;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
postResult(result);
}
return result;
}
};
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
mTaskInvoked.set(true);表示當(dāng)前任務(wù)已經(jīng)執(zhí)行過(guò)了。接著執(zhí)行doInBackground方法,最后將結(jié)果通過(guò)postResult(result);方法進(jìn)行傳遞。postResult()方法中通過(guò)sHandler來(lái)發(fā)送消息,sHandler的代碼如下:
private static class InternalHandler extends Handler {
public InternalHandler() {
super(Looper.getMainLooper());
}
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
public void handleMessage(Message msg) {
AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
// There is only one result
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
注意:AsyncTask中有兩個(gè)線(xiàn)程池,一個(gè)是SerialExecutor,另一個(gè)是THREAD_POOL_EXECUTOR,其中前者主要是任務(wù)進(jìn)行排隊(duì)的,后者才是真正的執(zhí)行任務(wù)。
而AsyncTask中還有一個(gè)方法InternalHandler,這個(gè)方法的主要作用是將執(zhí)行環(huán)境從線(xiàn)程池切換到主線(xiàn)程的。
以上就是淺談Android中AsyncTask的工作原理的詳細(xì)內(nèi)容,更多關(guān)于A(yíng)ndroid中AsyncTask的工作原理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
仿ios狀態(tài)欄顏色和標(biāo)題欄顏色一致的實(shí)例代碼
下面小編就為大家分享一篇仿ios狀態(tài)欄顏色和標(biāo)題欄顏色一致的實(shí)例代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-01-01
Android自動(dòng)填充短信驗(yàn)證碼功能(demo)
在項(xiàng)目開(kāi)發(fā)中為了給用戶(hù)帶來(lái)極好的體驗(yàn)效果,通常需要實(shí)現(xiàn)驗(yàn)證碼的自動(dòng)填充功能,怎么實(shí)現(xiàn)呢?今天小編給大家分享Android自動(dòng)填充短信驗(yàn)證碼功能的實(shí)現(xiàn)方法,需要的朋友參考下吧2017-02-02
淺析Android手機(jī)衛(wèi)士之號(hào)碼歸屬地查詢(xún)
這篇文章主要介紹了淺析Android手機(jī)衛(wèi)士之號(hào)碼歸屬地查詢(xún)的相關(guān)資料,需要的朋友可以參考下2016-04-04
Android限時(shí)搶購(gòu)倒計(jì)時(shí)實(shí)現(xiàn)代碼
這篇文章主要為大家詳細(xì)介紹了Android限時(shí)搶購(gòu)倒計(jì)時(shí)的實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02
Android自定義ImageView實(shí)現(xiàn)自動(dòng)放大縮小動(dòng)畫(huà)
這篇文章主要為大家詳細(xì)介紹了Android自定義ImageView實(shí)現(xiàn)自動(dòng)放大縮小動(dòng)畫(huà),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06
Android 自定義密碼輸入框?qū)崿F(xiàn)代碼
最近做個(gè)項(xiàng)目自定義密碼輸入框功能,下面小編把實(shí)現(xiàn)思路分享到腳本之家平臺(tái),需要的朋友參考下吧2018-03-03
Android 藍(lán)牙連接 ESC/POS 熱敏打印機(jī)打印實(shí)例(藍(lán)牙連接篇)
這篇文章主要介紹了Android 藍(lán)牙連接 ESC/POS 熱敏打印機(jī)打印實(shí)例(藍(lán)牙連接篇),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-04-04

