概要:
AsyncTask是一种轻量级的简单异步任务类,它可以在线程池中执行后台任务,然后把执行任务的进度
和执行任务的最终结果传递给主线程并在主线程中更新UI。
分析:
一,简单用法
AsyncTask的重要的方法:
1,onPreExecute() 运行在主线程,在doInBackgroud前执行,一般做一些准备工作。
2,doInBackground(String... params) 运行在后台线程池中,一般在这里处理耗时操作(文件读写,网络请求等);
在方法中调用publishProgress(params),更新任务进度;
在方法中调用cancel(Boolean),取消任务的执行(事实上是使onPostExecute无法执行)。
3,onProgressUpdate 在后台任务执行了publishProgress后,此方法会被调用4,onPostExecute() 任务执行后调用此方法。
这里除了doInBackground运行在工作线程中,其他都是运行在主线程中的。
AsyncTask的一帮代码应用:
1,自定义任务类继承AsyncTask。
执行任务:class MyAsyncTask extends AsyncTask<String, Integer, Integer> { public MyAsyncTask(){ super(); } @Override protected void onPreExecute() { super.onPreExecute(); Log.i(tag, "onPreExecute"); } @Override protected Integer doInBackground(String... params) { if (params != null && params.length > 0) { Log.i(tag, "doInBackground "+params[0]); } for (int i = 0; i < 3; i++) { try { Thread.sleep(1000); publishProgress(i); } catch (InterruptedException e) { e.printStackTrace(); } } cancel(true); return 1000; } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); Log.i(tag, "onProgressUpdate " + values[0]); } @Override protected void onPostExecute(Integer result) { super.onPostExecute(result); Log.i(tag, "onPostExecute " + result); } @Override protected void onCancelled() { super.onCancelled(); Log.i(tag, "onCancelled"); } }
new MyAsyncTask().execute("params");
二,源码分析
AsyncTask使用起来很简单,是因为我它对线程池和Handler进行了封装。现在了解一下他是如何封装的:
由任务执行的代码new MyAsyncTask().execute()可知:先是创建任务实例,然后执行execute()
先查看创建它实例的构造方法(构造方法必须在主线中执行):
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*/
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
Result result = doInBackground(mParams);
Binder.flushPendingCommands();
return postResult(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);
}
}
};
}
构造方法总结起来就是,创建了一个Callable(mWorker),并且把mWorker作为参数创建了FutrureTask
(mFuture,其实是个Runnable);
然后我继续看它的任务执行代码执行execute():
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
直接的调用了executeOnExecutor方法。
@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;
}
1,在上面方法中,当status为RUNNING,与FINISHED时,会抛出异常,这就解释了每个AsyncTask只能
执行一次execute方法。如果要再次执行任务,需要创建新的AsyncTask实例。
2,然后我们看到了我们熟悉的onPreExecute方法在这里执行。
我们继续跟踪exec.execute(mFuture)。
这里的exec就是上面的sDefaultExecutor
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);
}
}
1,mDefaultExecutor内部维持着一个任务队列mTasks,每次执行execute即添加任务到任务队列。
2,当mActive当前正执行的任务为null时scheduleNext(),
3,从scheduleNext()代码中可以看出,是取任务队列mTasks中的任务在线程池THREAD_POOL_EXECUTOR中执行。
4,mTasks任务队列在添加任务时,不是直接添加,而是包装了一个Runnable,在run中调用r.run(), 后面在finally{}中调用
scheduleNext,这就解释了,AsyncTask的任务现在都是串行执行的。
(这里要注意的是Android1.6-Android3.0版本中是并行的)。
这里的参数r,也就是mFuture是不是很面熟,它就是我们在最上面AsyncTask构造方法中,生成的FutureTask。
最后,mFuture.run()中会回调mWorker的call方法。
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
Result result = doInBackground(mParams);
Binder.flushPendingCommands();
return postResult(result);
}
1,我们在这里看到了doInbackgroud(),有前面的THREAD_POOL_EXECUTOR.execute(mActive)。这就解释它是在
线程池中执行的,也就是在工作线程中执行的。
我们接着追踪postResult
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
private static Handler getHandler() {
synchronized (AsyncTask.class) {
if (sHandler == null) {
sHandler = new InternalHandler();
}
return sHandler;
}
}
1,有上面分析可知psotResult即向InternalHandler发送消息,
接下来,我们看InternalHandler的内部实现。
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;
}
}
}
1,super(Looper.getMainLooper())表明它是一个主线程的Handler。
2,根据两种不同的消息处理,其中result就AsyncTaskResult,result.mTask就是AsyncTask自身。
3,我们在这里看到了onProgressUpdate(),因为publishProgress就是向sHandler发送MESSAGE_POST_PROGRESS
我们先看finish()
1,我们看到,它最终会调用onPostExecute。private void finish(Result result) { if (isCancelled()) { onCancelled(result); } else { onPostExecute(result); } mStatus = Status.FINISHED; }
public final boolean cancel(boolean mayInterruptIfRunning) { mCancelled.set(true); return mFuture.cancel(mayInterruptIfRunning); }
上面是cancel的代码,这就解释了我们调用cancel(true);的时候,onPostExecutor不执行,
因为它会执行onCancelled()方法。