為什么AsyncTask一定要在主線程中創(chuàng)建?execute方法一定要在主線程中調(diào)用?

關(guān)于為什么AsyncTask一定要在主線程中創(chuàng)建?

我們知道AsyncTask中UI的更新是通過InternalHandler實(shí)現(xiàn)的,這就說明InternalHandler必須是通過主線程的Loop來創(chuàng)建的。

看源碼

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的創(chuàng)建

private static HandlergetMainHandler() {

synchronized (AsyncTask.class) {

if (sHandler ==null) {

sHandler =new InternalHandler(Looper.getMainLooper());

        }

return sHandler;

    }

}

在API26中,InternalHandler 是通過Looper.getMainLooper()創(chuàng)建的,所以AsyncTask不論是在子線程還是主線程中創(chuàng)建都無所謂。在Android開發(fā)藝術(shù)探索一書中之所以強(qiáng)調(diào)AsyncTask必須在主線程中創(chuàng)建是因?yàn)橹霸创a中InternalHandler的創(chuàng)建方式如下:

private static final InternalHandler sHandler = new InternalHandler();

是通過當(dāng)前線程的Loop創(chuàng)建的,如果當(dāng)前線程是子線程,那自然是行不通的。

execute方法一定要在主線程中調(diào)用?

execute的源碼實(shí)現(xiàn)如下:
@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方法最先調(diào)用的是onPreExecute方法,而onPreExecute方法必須運(yùn)行在主線程,如果一定要在子線程中調(diào)execute方法那就表示你不能在onPreExecute方法中做更新UI的操作,因?yàn)榇藭r(shí)onPreExecute方法為子線程。onProgressUpdate, onPostExecute , onCancelled 方法仍然運(yùn)行在主線程(通過InternalHandler回調(diào)到主線程)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容