AsyncTask是对Handler与线程池的封装使用,使得耗时任务在后台执行,同时可以更新主线程ui等操作。通过阅读源码实现,分析内部实现机制:
Progress:AsyncTask所执行的后台任务的进度类型;
AsyncTask也可以通过并行的方式执行任务,只需调用executeOnExecutor方法,并传入THREAD_POOL_EXECUTOR作为其线程池即可。
AsyncTask的局限性:
1、必须在主线程创建,因为需要从后台线程切换到主线程,因此必须在主线程中创建sHandler。所以必须在主线程中加载AsyncTask类,是为了完成sHandler这个静态成员的初始化工作。
2、AsyncTask对象的execute方法必须在主线程中调用
3、一个AsyncTask对象只能调用一次execute方法,无论是正在执行或已结束,否则异常。
public abstract class AsyncTask<Params, Progress, Result>
Progress:AsyncTask所执行的后台任务的进度类型;
Result:后台任务的返回结果类型。
//AsyncTask成员函数,外部使用方不是必须实现,执行后台任务前的准备工作
protected void onPreExecute() {
}
//成员函数,必须实现,参数为Params
protected abstract Result doInBackground(Params... params);
//成员函数,非必须实现,参数为Progress,由publishProgress内部调用,表示任务进度更新
protected void onProgressUpdate(Progress... values) {}
//成员函数,非必须实现
protected void onPostExecute(Result result) {}
//成员函数,非必须实现,此方法会在后台任务被取消时被调用
protected void onCancelled() {}
public AsyncTask() {
//WorkRunnable抽象类实现了Callable<Result>
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);//表示任务已被激活调用
//设置线程优先级为后台级别
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
//注意!!调用doInBackground方法开始执行后台任务
Result result = doInBackground(mParams);
Binder.flushPendingCommands();
//postResult通过Handler发送消息到主线程,结果更新
return postResult(result);
}
};
/**
* FutureTask的直接子类(匿名内部类)的对象,参数是worker
* mFuture是一个封装了我们的后台任务的FutureTask对象,FutureTask类实现了FutureRunnable接口
* 通过这个接口可以方便的取消后台任务以及获取后台任务的执行结果
**/
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);
}
}
};
}
//WorkerRunnable接口的mParams接收参数,用于doInBackground
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
}
mFuture对象封装了call方法,当mFuture对象被提交到AsyncTask包含的线程池执行时,call方法就会被调用,我们定义的后台任务也就开始执行了.
FutureTask实现了RunnableFuture接口,可以看出RunnableFuture继承了Runnable接口和Future接口,而FutureTask实现了RunnableFuture接口。所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
//主线程处理onPostExecute和onProgressUpdate
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
//finish会执行onPostExecute
result.mTask.finish(result.mData[0]);
break;
//更新进度条
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
//默认情况,AsyncTask使用串行方式执行任务
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
//通过任务入队列,依次执行任务来串行执行
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 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();
//参数传递给worker
mWorker.mParams = params;
exec.execute(mFuture);
return this;
}
//真正执行任务的是THREAD_POOL_EXECUTOR
public static final Executor THREAD_POOL_EXECUTOR
= new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
其参数含义如下:
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE = 1;
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
}
};
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);
AsyncTask也可以通过并行的方式执行任务,只需调用executeOnExecutor方法,并传入THREAD_POOL_EXECUTOR作为其线程池即可。
AsyncTask的局限性:
1、必须在主线程创建,因为需要从后台线程切换到主线程,因此必须在主线程中创建sHandler。所以必须在主线程中加载AsyncTask类,是为了完成sHandler这个静态成员的初始化工作。
2、AsyncTask对象的execute方法必须在主线程中调用
3、一个AsyncTask对象只能调用一次execute方法,无论是正在执行或已结束,否则异常。