一:簡(jiǎn)單說下使用
AsyncTask是Google提供的輕量級(jí)的異步任務(wù)類,該類中實(shí)現(xiàn)了異步操作,并提供接口返回結(jié)果以及進(jìn)度
//這三個(gè)參數(shù)分別指,請(qǐng)求參數(shù)的類型,更新進(jìn)度的類型,返回結(jié)果的類型,沒有就寫Void
class MyAsyncTask extends AsyncTask<Void,Integer,String>{
//在子線程中執(zhí)行
@Override
protected String doInBackground(Void... params) {
return null;
}
//任務(wù)執(zhí)行前的操作,在main線程執(zhí)行
@Override
protected void onPreExecute() {
super.onPreExecute();
}
//返回結(jié)果,在main線程執(zhí)行
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
//更新進(jìn)度,在main線程執(zhí)行
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
}
使用:
MyAsyncTask task = new MyAsyncTask();
task.execute();
二:下面主要看下源碼
(1)首先看構(gòu)造方法
public AsyncTask() {
//asynctask的初始化就是初始化mWorker和Mfuture
//這一步可以簡(jiǎn)單的理解為根據(jù)傳入的參數(shù)準(zhǔn)備"Runnable"對(duì)象,然后扔到線程里面去執(zhí)行
//注意這里只是對(duì)mWorker進(jìn)行初始化,還沒有執(zhí)行,指的是還沒有放入到線程池里面執(zhí)行
//mWorker封裝的call()方法就是我們要在后臺(tái)執(zhí)行的方法
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
//doInBackground()方法需要我們自己實(shí)現(xiàn)
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
//獲得結(jié)果之后通過sHandler發(fā)出去
postResult(result);
}
return result;
}
};
//FutureTask可用于異步獲取執(zhí)行結(jié)果或取消執(zhí)行任務(wù)的場(chǎng)景趾徽。
// 通過傳入Runnable或者Callable的任務(wù)給FutureTask,
// 直接調(diào)用其run方法或者放入線程池執(zhí)行,之后可以在外部通過FutureTask的get方法異步獲取執(zhí)行結(jié)果仑撞,
// 因此私爷,F(xiàn)utureTask非常適合用于耗時(shí)的計(jì)算扫尖,主線程可以在完成自己的任務(wù)后伐坏,再去獲取結(jié)果。
// 另外击胜,F(xiàn)utureTask還可以確保即使調(diào)用了多次run方法亏狰,它都只會(huì)執(zhí)行一次Runnable或者Callable任務(wù),
// 或者通過cancel取消FutureTask的執(zhí)行等偶摔。
//這里mFuture對(duì)mWorker進(jìn)行封裝,也就是對(duì)mWorker的call()方法封裝,也就是說最終被放入到線程的是mFuture
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);
}
}
};
}
(2)然后再看execute()方法,看看mFuture是什么時(shí)候被提交到線程池執(zhí)行的
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
接著點(diǎn):
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
//如果不是未執(zhí)行的狀態(tài)
if (mStatus != Status.PENDING) {
switch (mStatus) {
case RUNNING:
//記住這個(gè)異常的名字
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();//在主線程執(zhí)行,準(zhǔn)確的說,在AysncTask實(shí)例化的線程執(zhí)行
mWorker.mParams = params;
//從這里可以看出執(zhí)行mFuture的是exec,那么exec是什么呢?
exec.execute(mFuture);
return this;
}
(3)exec就是sDefaultExecutor
接著看
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
我們先來(lái)看看SerialExecutor的官方解釋:
/**
* An {@link Executor} that executes tasks one at a time in serial
* order. This serialization is global to a particular process.
*/
簡(jiǎn)答說:這是一個(gè)通過串行方式每次執(zhí)行一個(gè)任務(wù)的Executor,而且在某個(gè)進(jìn)程中是全局的.
看看它的實(shí)現(xiàn):
private static class SerialExecutor implements Executor {
//這是一個(gè)任務(wù)隊(duì)列
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
public synchronized void execute(final Runnable r) {
//這個(gè)方法將r對(duì)象添加到隊(duì)列的尾部
mTasks.offer(new Runnable() {
//注意,這個(gè)run()方法不執(zhí)行r.run()就不會(huì)執(zhí)行
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
//取出隊(duì)列中的第一個(gè)Runnable對(duì)象,這個(gè)mActive就是mTasks.offer(new Runnable() 中new出來(lái)的Runnables
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
也就是說,SerialExecutor內(nèi)部維持一個(gè)任務(wù)隊(duì)列,有任務(wù)來(lái)的時(shí)候就把任務(wù)加入到隊(duì)列里面,然后從任務(wù)隊(duì)列里面取出一個(gè)任務(wù)放入到THREAD_POOL_EXECUTOR執(zhí)行.
THREAD_POOL_EXECUTOR就是一個(gè)線程池,不用多說了.
也就是說SerialExecutor最大的作用就是保證任務(wù)一個(gè)一個(gè)的串行處理,真正處理的是THREAD_POOL_EXECUTOR.
(4)任務(wù)已經(jīng)執(zhí)行了,我們?cè)趺传@取結(jié)果呢?下面再回過頭來(lái)看看最開始的構(gòu)造方法里面的postResult(result)方法
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
//getHandler()這個(gè)方法返回一個(gè)handler,通過handler. obtainMessage()方法獲取一個(gè)target對(duì)象是該handler的Message對(duì)象
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
我們看看getHandler()方法
private static Handler getHandler() {
synchronized (AsyncTask.class) {
if (sHandler == null) {
sHandler = new InternalHandler();
}
return sHandler;
}
}
再看看InternalHandler
private static class InternalHandler extends Handler {
public InternalHandler() {
//看過handler源碼的對(duì)這里應(yīng)該比較熟悉,沒看過的建議去看看
super(Looper.getMainLooper());
}
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
public void handleMessage(Message msg) {
AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
//根據(jù)msg的不同類型執(zhí)行不同的操作,這里跟我們平常寫handler是一樣的
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;
}
}
}
三:幾個(gè)問題
(1)AsyncTask的串行并行執(zhí)行問題(源碼中已經(jīng)說明是串行執(zhí)行了)
做個(gè)試驗(yàn):
MyAsyncTask task1 = new MyAsyncTask();
task1.execute("1");
MyAsyncTask task2 = new MyAsyncTask();
task2.execute("2");
MyAsyncTask task3 = new MyAsyncTask();
task3.execute("3");
在doInBackground()方法里做簡(jiǎn)單處理
protected String doInBackground(String... params) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(params[0]);
return null;
}
結(jié)果:
17:21:50.557 8849-8880/com.dgtech.sss.asynctaskdemo I/System.out: 1
17:21:51.566 8849-8950/com.dgtech.sss.asynctaskdemo I/System.out: 2
17:21:52.568 8849-9010/com.dgtech.sss.asynctaskdemo I/System.out: 3
從執(zhí)行結(jié)果(時(shí)間)來(lái)看,是串行的
那么有沒有辦法可以并行執(zhí)行呢?
答案是肯定的,用executeOnExecutor()
這個(gè)方法傳入的第一個(gè)參數(shù)是一個(gè)線程池,第二個(gè)參數(shù)是請(qǐng)求的參數(shù)
使用這個(gè)方法也就是繞過了SerialExecutor這個(gè)類,不再由這個(gè)類進(jìn)行隊(duì)列處理,當(dāng)然就并發(fā)執(zhí)行了
試驗(yàn):
MyAsyncTask task1 = new MyAsyncTask();
task1.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"1");
MyAsyncTask task2 = new MyAsyncTask();
task2.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"2");
MyAsyncTask task3 = new MyAsyncTask();
task3.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"3");
結(jié)果:
17:27:57.265 19387-19408/com.dgtech.sss.asynctaskdemo I/System.out: 1
17:27:57.267 19387-19410/com.dgtech.sss.asynctaskdemo I/System.out: 3
17:27:57.269 19387-19409/com.dgtech.sss.asynctaskdemo I/System.out: 2
(2)一個(gè)AsyncTask對(duì)象只能執(zhí)行一次execute()方法,否則會(huì)報(bào)異常:
"Cannot execute task the task is already running."
(3)防止內(nèi)存泄漏,應(yīng)該在Activity銷毀前執(zhí)行task.cancel(true)取消task的執(zhí)行
(4)當(dāng)內(nèi)存不足或者屏幕旋轉(zhuǎn)導(dǎo)致Activity重建,此時(shí)舊的AsyncTask持有舊的Activity引用,因此不能更新返回結(jié)果更新UI