关于为什么AsyncTask一定要在主线程中创建?
我们知道AsyncTask中UI的更新是通过InternalHandler实现的,这就说明InternalHandler必须是通过主线程的Loop来创建的。
看源码
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;
}
}
}
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
}else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
InternalHandler的创建
private static HandlergetMainHandler() {
synchronized (AsyncTask.class) {
if (sHandler ==null) {
sHandler =new InternalHandler(Looper.getMainLooper());
}
return sHandler;
}
}
在API26中,InternalHandler 是通过Looper.getMainLooper()创建的,所以AsyncTask不论是在子线程还是主线程中创建都无所谓。在Android开发艺术探索一书中之所以强调AsyncTask必须在主线程中创建是因为之前源码中InternalHandler的创建方式如下:
private static final InternalHandler sHandler = new InternalHandler();
是通过当前线程的Loop创建的,如果当前线程是子线程,那自然是行不通的。
execute方法一定要在主线程中调用?
execute的源码实现如下:
@MainThread
public final AsyncTaskexecute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
@MainThread
public final AsyncTaskexecuteOnExecutor(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;
}
@MainThread
protected void onPreExecute() {
}
通过源码可以看出,execute方法最先调用的是onPreExecute方法,而onPreExecute方法必须运行在主线程,如果一定要在子线程中调execute方法那就表示你不能在onPreExecute方法中做更新UI的操作,因为此时onPreExecute方法为子线程。onProgressUpdate, onPostExecute , onCancelled 方法仍然运行在主线程(通过InternalHandler回调到主线程)。
网友评论