为什么AsyncTask一定要在主线程中创建?execute方法一定要在主线程中调用?

关于为什么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回调到主线程)。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容