a亚洲精品_精品国产91乱码一区二区三区_亚洲精品在线免费观看视频_欧美日韩亚洲国产综合_久久久久久久久久久成人_在线区

首頁 > 系統(tǒng) > Android > 正文

Android AsyncTask源碼分析

2019-12-12 06:41:29
字體:
供稿:網(wǎng)友

Android中只能在主線程中進(jìn)行UI操作,如果是其它子線程,需要借助異步消息處理機(jī)制Handler。除此之外,還有個(gè)非常方便的AsyncTask類,這個(gè)類內(nèi)部封裝了Handler和線程池。本文先簡要介紹AsyncTask的用法,然后分析具體實(shí)現(xiàn)。

基本用法
AsyncTask是一個(gè)抽象類,我們需要?jiǎng)?chuàng)建子類去繼承它,并且重寫一些方法。AsyncTask接受三個(gè)泛型參數(shù):

Params: 指定傳給任務(wù)執(zhí)行時(shí)的參數(shù)的類型
Progress: 指定后臺(tái)任務(wù)執(zhí)行時(shí)將任務(wù)進(jìn)度返回給UI線程的參數(shù)類型
Result: 指定任務(wù)完成后返回的結(jié)果的類型
除了指定泛型參數(shù),還需要根據(jù)需要重寫一些方法,常用的如下:

onPreExecute(): 這個(gè)方法在UI線程調(diào)用,用于在任務(wù)執(zhí)行前做一些初始化操作,如在界面上顯示加載進(jìn)度控件
doInBackground: 在onPreExecute()結(jié)束之后立刻在后臺(tái)線程調(diào)用,用于耗時(shí)操作。在這個(gè)方法中可調(diào)用publishProgress方法返回任務(wù)的執(zhí)行進(jìn)度
onProgressUpdate: 在doInBackground調(diào)用publishProgress后被調(diào)用,工作在UI線程
onPostExecute: 后臺(tái)任務(wù)結(jié)束后被調(diào)用,工作在UI線程
源碼分析
下面分析這個(gè)類的實(shí)現(xiàn),主要有線程池以及Handler兩部分。

1、線程池
當(dāng)執(zhí)行一個(gè)AsyncTask的時(shí)候調(diào)用的是execute()方法,就從這個(gè)開始看:

public final AsyncTask<Params, Progress, Result> execute(Params... params){ return executeOnExecutor(sDefaultExecutor, params);}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;  //先執(zhí)行 onPreExecute onPreExecute();   mWorker.mParams = params;   exec.execute(mFuture);  return this; } 

execute方法會(huì)調(diào)用executeOnExecutor。在這個(gè)方法中先檢查任務(wù)是否已經(jīng)執(zhí)行或者執(zhí)行結(jié)束,然后把任務(wù)標(biāo)記為running。最開始執(zhí)行的是onPreExecute,接著把參數(shù)賦值給mWorker對象。這個(gè)mWorker是一個(gè)Callable對象,最終被包裝為FutureTask,代碼如下:

private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {  Params[] mParams; } mWorker = new WorkerRunnable<Params, Result>() {   public Result call() throws Exception {    mTaskInvoked.set(true);    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);    //noinspection unchecked    return postResult(doInBackground(mParams));   }  }; 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 occured while executing doInBackground()",      e.getCause());   } catch (CancellationException e) {    postResultIfNotInvoked(null);   }  } }; 

從上面的代碼可以看出,在mWorker對象中的call()方法會(huì)調(diào)用doInbackground,返回值交給postResult方法,這個(gè)方法通過Handler發(fā)送消息,這一點(diǎn)稍后再詳細(xì)分析。

在mWorker對象被封裝成FutureTask之后交由線程池執(zhí)行,從execute方法可以看出,使用的是sDefaultExecutor,它的值默認(rèn)為SERIAL_EXECUTOR,也就是串行執(zhí)行器,實(shí)現(xiàn)如下:

 private static class SerialExecutor implements Executor {  //線性雙向隊(duì)列,用來存儲(chǔ)所有的AsyncTask任務(wù)  final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();  //當(dāng)前正在執(zhí)行的AsyncTask任務(wù)  Runnable mActive;  public synchronized void execute(final Runnable r) {   //將新的AsyncTask任務(wù)加入到雙向隊(duì)列中   mTasks.offer(new Runnable() {    public void run() {     try {      //執(zhí)行AsyncTask任務(wù)      r.run();     } finally {      //當(dāng)前任務(wù)執(zhí)行結(jié)束后執(zhí)行下一個(gè)任務(wù)     scheduleNext();     }    }   });   if (mActive == null) {    scheduleNext();   }  }  protected synchronized void scheduleNext() {   //從任務(wù)隊(duì)列中取出隊(duì)列頭部的任務(wù),如果有就交給并發(fā)線程池去執(zhí)行   if ((mActive = mTasks.poll()) != null) {    THREAD_POOL_EXECUTOR.execute(mActive);   }  } }public static final Executor THREAD_POOL_EXECUTOR   = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,     TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory); 

在上面的代碼中,如果有任務(wù)執(zhí)行,那么SerialExecutor的execute方法會(huì)被調(diào)用,它的邏輯是把Runnable對象加入ArrayDeque隊(duì)列中,然后判斷mActivie是否為空。第一次執(zhí)行時(shí)mActive當(dāng)然為空,所以執(zhí)行scheduleNext,其實(shí)就是取出任務(wù)隊(duì)列中的第一個(gè)任務(wù)交給線程池(THREAD_POOL_EXECUTOR)執(zhí)行。加入mTask隊(duì)列的Runnable對象的run方法里最終一定會(huì)調(diào)用scheduleNext,那么又會(huì)從任務(wù)隊(duì)列中取出隊(duì)頭任務(wù)執(zhí)行。這樣便實(shí)現(xiàn)了單線程順序執(zhí)行任務(wù),所以在AsyncTask中默認(rèn)啟用的是單線程執(zhí)行,只有上一個(gè)任務(wù)執(zhí)行后才會(huì)執(zhí)行下一個(gè)任務(wù)。如果想要啟用多線程執(zhí)行任務(wù),可以直接調(diào)用 executeOnExecutor(Executor exec,  Params... params),這里的Executor參數(shù)可以使用AsyncTask自帶的THREAD_POOL_EXECUTOR,也可以自己定義。

2、Handler
AsyncTask內(nèi)部用Handler傳遞消息,它的實(shí)現(xiàn)如下:

private static class InternalHandler extends Handler {  @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;   }  } } 

如果消息類型是任務(wù)執(zhí)行后的返回值(MESSAGE_POST_RESULT)將調(diào)用finish()方法:

private void finish(Result result) {  if (isCancelled()) {   onCancelled(result);  } else {   onPostExecute(result);  }  mStatus = Status.FINISHED; } 

從上面可以知道,如果任務(wù)取消了,將調(diào)用onCancelled,否則調(diào)用onPostExecute,所以一個(gè)AsyncTask任務(wù)如果取消了,那么onPostExecute將不會(huì)得到執(zhí)行。

如果消息類型是執(zhí)行進(jìn)度(MESSAGE_POST_PROGRESS)將調(diào)用onProgressUpdate,這個(gè)方法默認(rèn)是空方法,我們可以根據(jù)自己的需要重寫。

總結(jié)
AsyncTask的主要邏輯就如上面所分析的,總結(jié)幾個(gè)需要注意的地方:

      1)、 AsyncTask的類必須在UI線程加載(從4.1開始系統(tǒng)會(huì)幫我們自動(dòng)完成)
      2)、  AsyncTask對象必須在UI線程創(chuàng)建
      3)、  execute方法必須在UI線程調(diào)用
      4)、  不要手動(dòng)調(diào)用onPreExecute()、doInBackground、onProgressUpdate方法
      5)、  一個(gè)任務(wù)只能被調(diào)用一次(第二次調(diào)用會(huì)拋出異常)

其它還有一些細(xì)節(jié)可以自行研究源碼,另外推薦幾篇不錯(cuò)的文章:

Android AsyncTask完全解析,帶你從源碼的角度徹底理解

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 天天摸夜夜摸爽爽狠狠婷婷97 | 中国一级毛片 | 天天躁日日躁狠狠很躁 | 黄色影视免费观看 | 国产精品久久91 | 国产精品理论在线观看 | 中文字幕在线精品 | 91精品国产乱码久久久久久 | 久久91久久久久麻豆精品 | 欧美色图一区 | 亚洲二区视频 | 天天操天天舔天天爽 | 成人精品一区二区三区中文字幕 | 精品国产一区二区三区在线观看 | 欧美视频免费看 | 国产精品片www48888 | 国产精品久久一区 | 视频羞羞| 国产精品一区二区免费看 | 午夜精品久久久久 | 国产精品欧美久久久久一区二区 | 欧美日韩成人在线视频 | 国产欧美一区二区精品性色 | 黄色一级免费电影 | 黄色高清网站 | 狠狠色综合欧美激情 | 成人免费毛片高清视频 | 91免费版在线观看 | 青青久久av北条麻妃海外网 | 一区二区三区精品视频 | 国产精品视频一区二区免费不卡 | 亚洲无吗电影 | 中文字幕av一区二区三区 | 成人精品一区二区三区中文字幕 | 国产美女高潮一区二区三区 | 久久兔费看a级 | 欧美一区 | 激情91 | 免费看国产一级特黄aaaa大片 | 欧美视频免费在线 | 国产精品第一国产精品 |