一篇搞懂AsynsTask

what

android 使用模板模式,封装用于执行异步任务。在android中通常情况下需要实现多线程任务以及UI的更新,但是UI通常情况下只能由UI线程来更新,我们一般简单点可能会使用handler啊,runOnUI方法啊,其实本质也是使用UI主线程的handler。但是写起来很好看不方便,所以android使用handler和线程池封装了一个用于执行异步的AsyncTask。

how

首先看看怎么用吧,巨简单。

继承AsyncTask

三泛型代表:

  • Params 输入参数类型
  • Result 执行结果类型
  • Progress 进度量类型

依次重写构造方法:

  • doInBackground 具体任务执行
  • onPreExecute 任务之前,UI线程,一般用于添加执行开始提示
  • onPostExecute 任务执行之后,UI线程,用于添加执行完成提示
  • onProgressUpdate 进度变化回调,UI线程,用于添加进度提示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

public class DeleteAsyncTask extends AsyncTask<ArrayList<Model>, Integer, Boolean> {
public DeleteAsyncTask() {
}
@Override
protected Boolean doInBackground(ArrayList<Model>... lists) {
return delete(lists[0]);
}
@Override
protected void onPreExecute() {
}
@Override
protected void onPostExecute(Boolean succeed) {
}
@Override
protected void onProgressUpdate(Integer[] values) {
}
}

新建实例,执行

这个是使用默认线程池,会去排队的哦(串行执行)

1
new DeleteAsyncTask().execute(mSelectedList);

你要觉得不爽,或者你的任务很特别是那种IO任务啊,或者计算任务啊。指定你的线程池

1
new DeleteAsyncTask().executeOnExecutor(executor,mSelectedList);

why

首先讲下为啥以execute(paramm)的方式执行AsyncTask是串行的执行的。为啥呢,因为AsyncTask内部是维持了两个线程池,SERIAL_EXECUTOR:用于任务排队即所有任务顺序执行的线程池。THREAD_POOL_EXECUTOR:用于实际执行任务的线程池,调用execute时会通过SERIAL_EXECUTOR来执行,而这个则是入队列,然后调用THREAD_POOL_EXECUTOR来实际执行任务。对了他们都是静态的。

AsyncTask状态

1
2
3
4
5
public enum Status {
PENDING,//即将
RUNNING,//正在执行
FINISHED,//结束
}

SERIAL_EXECUTOR线程池

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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);//调用实际的线程池
}
}
}

THREAD_POOL_EXECUTOR 线程池

1
2
3
4
5
6
7
8
public static final Executor THREAD_POOL_EXECUTOR;
static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}

InternalHandler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private static class InternalHandler extends Handler {
public InternalHandler(Looper looper) {
super(looper);
}
@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;
}
}
}

首先从构造方法看

最终都会调用参数为Looper的构造方法,在构造方法里面进行获得UI handler,以及初始化CallAble和FutureTask

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
 public AsyncTask() {
this((Looper) null);
}
public AsyncTask(@Nullable Handler handler) {
this(handler != null ? handler.getLooper() : null);
}
public AsyncTask(@Nullable Looper callbackLooper) {
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
? getMainHandler()//自定义的主线程handler,返回的静态的UI handler
: new Handler(callbackLooper);//handler
//构建callable
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);//发送结果,也就最终会触发OnPostExecute
}
return result;
}
};
//构建FutureTask保存结果
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);//发送结果
}
}
};
}

看execute执行

1
2
3
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);//启用默认串行线程池
}

走向executeOnExecutor,当然我们也可以调,这个就是说让任务在传入的线程池中运行

首先判断标志位是否合格,也就是执行过的或者执行完的都不能再次执行了。回调onPreExecute,然后添加参数进入线程池

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
if (mStatus != Status.PENDING) {//Async任务执行执行前状态必须为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;
}

来到串行线程池

将任务入队列,顺序执行,调用实际的线程池

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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);//调用实际的线程池
}
}
}

几个回调

doInBackground

在Callable中执行的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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);//发送结果,也就最终会触发OnPostExecute
}
return result;
}
};

onPreExecute

在任务进入线程池之前执行

1
2
3
4
mStatus = Status.RUNNING;//修改状态
onPreExecute();//回调执行前
mWorker.mParams = params;//添加参数
exec.execute(mFuture);//进入线程池

onPostExecute

handler发送结果后finish中执行

1
2
3
4
5
6
7
8
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);//触发取消
} else {
onPostExecute(result);//结束
}
mStatus = Status.FINISHED;
}

onProgressUpdate

在手动调用publishProgress,handler发送消息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
   protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}


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;
}

onCancelled

使用cancel,取消任务

1
2
3
4
public final boolean cancel(boolean mayInterruptIfRunning) {
mCancelled.set(true);//设置判断位
return mFuture.cancel(mayInterruptIfRunning);//中断任务执行
}