为什么要入坑?
1.新建AsyncTask的实例时重写的方法为什么有的在子线程执行,有的在主线程执行?
2.AsyncTask是怎么实现异步的呢?
1.执行入口
AsyncTask task = new AsyncTask
task.execute();
2.判断task的状态(状态不对就会抛出异常)
@MainThread
public final AsyncTask 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;
}
从源码中可以看出,onPreExecute方法确实在主线程中执行。
问:AsyncTask为什么只能执行一次?
答:从源码中可以看出,如果task是运行中的状态,则会抛出IllegalStateException的异常
3.在AsyncTask构造方法中创建mFuture实例(实质上是Runnable的实现类)
public AsyncTask() {
...
mFuture = new FutureTask(mWorker) {...}
...
}
public class FutureTask implements RunnableFuture {...}
public interface RunnableFuture extends Runnable, Future {
void run();
}
在FutureTask会重写run方法,发现最终会调用c.call()方法
public void run() {
if (state != NEW ||
!U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
return;
try {
Callable c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
//核心代码在这里
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}
call()方法哪里来的呢:
4.在AsyncTask构造方法中创建mWorker实例
public AsyncTask() {
...
mWorker = new WorkerRunnable() {
//我在这呢!!!
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;
}
};
...
}
从源码可以看出doInBackground会在FutureTask重写的run方法中执行,所以它是运行在子线程的。
其实FutureTask的实例会重写done方法,而他们最终也会走 postResult(result);
mFuture = new FutureTask(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);
}
}
};
private void postResultIfNotInvoked(Result result) {
final boolean wasTaskInvoked = mTaskInvoked.get();
if (!wasTaskInvoked) {
postResult(result);
}
}
5.调用postResult方法(通过handler发送消息切换到主线程中)
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult(this, result));
message.sendToTarget();
return result;
}
6.通过handleMessage处理消息
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:
//核心代码!!!最终会执行这里
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
通过Looper.getMainLooper();拿到了主线程的轮询器,现在已经回到主线程啦
7.最后会调用AsyncTask的finish方法
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
//回调方法在这里呢
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
通过上一步,已经回到了主线程,所以 onPostExecute(result);必然是在主线程中执行的
最后说一句
本文只是对源码的简单查看,仍然有很多不解和疑惑。此文仅作为一个学习笔记