最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android AsyncTask源碼分析

 更新時(shí)間:2016年04月05日 14:25:32   作者:然則  
這篇文章主要針對(duì)Android AsyncTask源碼為大家進(jìn)行分析,非常方便的AsyncTask類內(nèi)部封裝了Handler和線程池,感興趣的小伙伴們可以參考一下

Android中只能在主線程中進(jìn)行UI操作,如果是其它子線程,需要借助異步消息處理機(jī)制Handler。除此之外,還有個(gè)非常方便的AsyncTask類,這個(gè)類內(nèi)部封裝了Handler和線程池。本文先簡(jiǎn)要介紹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對(duì)象。這個(gè)mWorker是一個(gè)Callable對(duì)象,最終被包裝為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對(duì)象中的call()方法會(huì)調(diào)用doInbackground,返回值交給postResult方法,這個(gè)方法通過Handler發(fā)送消息,這一點(diǎn)稍后再詳細(xì)分析。

在mWorker對(duì)象被封裝成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對(duì)象加入ArrayDeque隊(duì)列中,然后判斷mActivie是否為空。第一次執(zhí)行時(shí)mActive當(dāng)然為空,所以執(zhí)行scheduleNext,其實(shí)就是取出任務(wù)隊(duì)列中的第一個(gè)任務(wù)交給線程池(THREAD_POOL_EXECUTOR)執(zhí)行。加入mTask隊(duì)列的Runnable對(duì)象的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對(duì)象必須在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完全解析,帶你從源碼的角度徹底理解

相關(guān)文章

  • Android實(shí)例HandlerThread源碼分析

    Android實(shí)例HandlerThread源碼分析

    本篇文章主要給大家通過實(shí)例代碼分析了Android中HandlerThread的用法以及步驟,需要的朋友參考學(xué)習(xí)下吧。
    2017-12-12
  • Android  ActionBar控件操作使用詳解

    Android  ActionBar控件操作使用詳解

    這篇文章主要介紹了Android  ActionBar控件操作使用,ActionBar是Android常用的導(dǎo)航控件,位于activity的頂部,用于顯示標(biāo)題,導(dǎo)航icon和actions等等
    2023-04-04
  • Android管理與操作Wifi簡(jiǎn)單實(shí)例源碼

    Android管理與操作Wifi簡(jiǎn)單實(shí)例源碼

    這篇文章主要介紹了Android管理與操作Wifi簡(jiǎn)單實(shí)例源碼的相關(guān)資料,需要的朋友可以參考下
    2016-02-02
  • Android ListView適配器(Adapter)優(yōu)化方法詳解

    Android ListView適配器(Adapter)優(yōu)化方法詳解

    這篇文章主要介紹了Android ListView優(yōu)化方法詳解的相關(guān)資料,這里舉例說明該如何對(duì)ListView 進(jìn)行優(yōu)化,具有一定的參考價(jià)值,需要的朋友可以參考下
    2016-11-11
  • 詳解Andorid開發(fā)中反射機(jī)制是怎么一回事

    詳解Andorid開發(fā)中反射機(jī)制是怎么一回事

    反射機(jī)制是在運(yùn)行狀態(tài)中,對(duì)于任何一個(gè)類,都可以知道這個(gè)類的所有屬性和方法,對(duì)于任何一個(gè)對(duì)象,都可以調(diào)用它所有的方法和屬性,修改部分類型信息,這種動(dòng)態(tài)獲取信息以及動(dòng)態(tài)調(diào)用對(duì)象方法的功能稱為Java的反射機(jī)制
    2022-11-11
  • Flutter封裝組動(dòng)畫混合動(dòng)畫AnimatedGroup示例詳解

    Flutter封裝組動(dòng)畫混合動(dòng)畫AnimatedGroup示例詳解

    這篇文章主要為大家介紹了Flutter封裝組動(dòng)畫混合動(dòng)畫AnimatedGroup示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • 一些比較實(shí)用的 Android adb 命令分享

    一些比較實(shí)用的 Android adb 命令分享

    這篇文章主要介紹了一些比較實(shí)用的 Android adb 命令分享,本文講解了查看設(shè)備、安裝應(yīng)用、卸載一個(gè)應(yīng)用、啟動(dòng)一個(gè)頁(yè)面、進(jìn)入設(shè)備的shell界面等內(nèi)容,需要的朋友可以參考下
    2015-02-02
  • Android ANR原理分析

    Android ANR原理分析

    ANR即Application Not Responding,顧名思義就是應(yīng)用程序無響應(yīng)。在Android中,一般情況下,四大組件均是工作在主線程中的,Android會(huì)隨時(shí)監(jiān)控應(yīng)用程序的響應(yīng)情況,如果因?yàn)橐恍┖臅r(shí)操作,那么系統(tǒng)就會(huì)顯示ANR對(duì)話框提示用戶對(duì)應(yīng)的應(yīng)用處于無響應(yīng)狀態(tài)
    2021-06-06
  • API處理Android安全距離詳情

    API處理Android安全距離詳情

    這篇文章主要介紹了API處理Android安全距離詳情,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下
    2022-06-06
  • Android框架組件Lifecycle的使用詳解

    Android框架組件Lifecycle的使用詳解

    這篇文章主要介紹了Android框架組件Lifecycle的使用詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-07-07

最新評(píng)論

马公市| 开封市| 老河口市| 梨树县| 安阳县| 遂平县| 成都市| 康平县| 平罗县| 余江县| 娄底市| 永和县| 台安县| 阿城市| 泰州市| 河南省| 美姑县| 儋州市| 余庆县| 屏山县| 奉节县| 许昌市| 清苑县| 两当县| 子洲县| 武汉市| 昔阳县| 巴彦淖尔市| 盐津县| 新蔡县| 台湾省| 扎囊县| 新绛县| 安丘市| 绵阳市| 宁河县| 扶沟县| 昭平县| 玛曲县| 舟曲县| 静海县|