亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > Android > 正文

Android AsyncTask源碼分析

2019-12-12 06:41:29
字體:
來源:轉載
供稿:網友

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

基本用法
AsyncTask是一個抽象類,我們需要創建子類去繼承它,并且重寫一些方法。AsyncTask接受三個泛型參數:

Params: 指定傳給任務執行時的參數的類型
Progress: 指定后臺任務執行時將任務進度返回給UI線程的參數類型
Result: 指定任務完成后返回的結果的類型
除了指定泛型參數,還需要根據需要重寫一些方法,常用的如下:

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

1、線程池
當執行一個AsyncTask的時候調用的是execute()方法,就從這個開始看:

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;  //先執行 onPreExecute onPreExecute();   mWorker.mParams = params;   exec.execute(mFuture);  return this; } 

execute方法會調用executeOnExecutor。在這個方法中先檢查任務是否已經執行或者執行結束,然后把任務標記為running。最開始執行的是onPreExecute,接著把參數賦值給mWorker對象。這個mWorker是一個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()方法會調用doInbackground,返回值交給postResult方法,這個方法通過Handler發送消息,這一點稍后再詳細分析。

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

 private static class SerialExecutor implements Executor {  //線性雙向隊列,用來存儲所有的AsyncTask任務  final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();  //當前正在執行的AsyncTask任務  Runnable mActive;  public synchronized void execute(final Runnable r) {   //將新的AsyncTask任務加入到雙向隊列中   mTasks.offer(new Runnable() {    public void run() {     try {      //執行AsyncTask任務      r.run();     } finally {      //當前任務執行結束后執行下一個任務     scheduleNext();     }    }   });   if (mActive == null) {    scheduleNext();   }  }  protected synchronized void scheduleNext() {   //從任務隊列中取出隊列頭部的任務,如果有就交給并發線程池去執行   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); 

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

2、Handler
AsyncTask內部用Handler傳遞消息,它的實現如下:

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;   }  } } 

如果消息類型是任務執行后的返回值(MESSAGE_POST_RESULT)將調用finish()方法:

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

從上面可以知道,如果任務取消了,將調用onCancelled,否則調用onPostExecute,所以一個AsyncTask任務如果取消了,那么onPostExecute將不會得到執行。

如果消息類型是執行進度(MESSAGE_POST_PROGRESS)將調用onProgressUpdate,這個方法默認是空方法,我們可以根據自己的需要重寫。

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

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

其它還有一些細節可以自行研究源碼,另外推薦幾篇不錯的文章:

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

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
色悠悠国产精品| 欧美成人中文字幕在线| 日韩精品有码在线观看| 日韩欧美国产黄色| 亚洲天堂成人在线视频| 国产香蕉精品视频一区二区三区| 精品视频一区在线视频| 国产成人精品免费视频| 亚洲欧洲第一视频| 青青青国产精品一区二区| 国产婷婷色综合av蜜臀av| 8090成年在线看片午夜| 国产精品视频最多的网站| 亚洲激情视频在线观看| 欧美在线视频在线播放完整版免费观看| 精品网站999www| 日韩av在线一区二区| 欧美日韩中文字幕在线视频| 久久人人爽人人爽人人片av高清| 丝袜美腿精品国产二区| 成人网在线视频| 高清日韩电视剧大全免费播放在线观看| 97精品在线观看| 久久人人爽人人爽爽久久| 欧美久久精品午夜青青大伊人| 亚洲一区中文字幕| 国产福利精品av综合导导航| 91国偷自产一区二区三区的观看方式| 亚洲欧美自拍一区| 亚洲高清一二三区| 亚洲激情小视频| 国产精品第一页在线| 91社影院在线观看| 91精品国产91久久久久久久久| 亚洲国产精品va在线看黑人动漫| 亚洲精品电影久久久| 国产自摸综合网| 亚洲香蕉伊综合在人在线视看| 国产精品久久久久久中文字| 性欧美在线看片a免费观看| 4438全国亚洲精品在线观看视频| 亚洲天堂开心观看| 91久久久久久久| 亚洲欧美激情另类校园| 欧美大荫蒂xxx| 欧美性猛交xxxx乱大交| 国产精品久久久久一区二区| 欧美最顶级的aⅴ艳星| 中文字幕亚洲天堂| 亚洲欧美日韩第一区| 亚洲第一av网站| 久久男人资源视频| 久久香蕉国产线看观看网| 欧美成人精品一区二区| 色综合久久中文字幕综合网小说| 久久久久久九九九| 91视频国产高清| 欧美与欧洲交xxxx免费观看| 国产丝袜高跟一区| 亚洲自拍偷拍区| 亚洲韩国青草视频| 亚洲精品电影网| 亚洲免费av片| 97超碰色婷婷| 中文字幕欧美日韩| 亚洲裸体xxxx| 搡老女人一区二区三区视频tv| 久久综合九色九九| 欧美男插女视频| 色播久久人人爽人人爽人人片视av| 美日韩精品免费视频| 精品国产鲁一鲁一区二区张丽| 亚洲国产日韩欧美在线99| 久久99亚洲热视| 亚洲国产婷婷香蕉久久久久久| 亚洲区中文字幕| 久久久久久久亚洲精品| 久久久91精品国产一区不卡| 亚洲精品电影久久久| 欧美成人精品一区二区三区| 26uuu另类亚洲欧美日本老年| 日韩av不卡在线| 国产精品高精视频免费| 国产一区二区三区高清在线观看| 亚洲男人第一网站| 国产欧美久久一区二区| 日韩小视频在线| 日韩欧美国产一区二区| 日韩电影免费观看中文字幕| 欧美性视频在线| 亚洲国产成人久久| 国产91网红主播在线观看| 中文字幕欧美专区| 中文字幕不卡在线视频极品| 日韩av在线免费观看一区| 久久久91精品国产| 国产欧美日韩免费看aⅴ视频| 欧美精品18videos性欧美| 日韩精品免费一线在线观看| 亚洲欧美日韩图片| 成人av.网址在线网站| 精品女厕一区二区三区| 日韩中文字幕免费视频| 亚洲女人初尝黑人巨大| 久久99久久99精品中文字幕| 91精品国产乱码久久久久久蜜臀| 亚洲精品国产欧美| 不卡毛片在线看| 欧美色播在线播放| 色偷偷噜噜噜亚洲男人的天堂| 人妖精品videosex性欧美| 国产综合香蕉五月婷在线| zzijzzij亚洲日本成熟少妇| 久久露脸国产精品| 国产精品狼人色视频一区| 8050国产精品久久久久久| 亚洲最大福利视频| 亚洲成色www8888| 欧美性极品xxxx娇小| 国产一区视频在线播放| 中日韩美女免费视频网址在线观看| 欧美电影免费观看高清完整| 欧美日韩国产成人在线| 久久精品99久久久香蕉| 亚洲第一二三四五区| 国产精品久久久久福利| 成人午夜在线视频一区| 久久久影视精品| 欧美日韩一区二区在线播放| 亚洲第一精品夜夜躁人人躁| 日韩中文av在线| 成人a视频在线观看| 精品国产一区二区三区久久久狼| 狠狠色狠狠色综合日日五| 久热精品视频在线观看一区| 丝袜亚洲另类欧美重口| 亚洲精品成人久久电影| 亚洲欧美日韩高清| 综合国产在线观看| 91国内在线视频| 最近2019中文字幕第三页视频| 情事1991在线| 欧美有码在线观看视频| 亚洲国产精品va在线看黑人动漫| 视频在线观看一区二区| www.日韩免费| 亚洲视频在线免费观看| 亚洲精品久久久久中文字幕二区| 亚洲成人1234| 日韩在线一区二区三区免费视频| 日韩一区二区在线视频| 欧美疯狂做受xxxx高潮| 一区二区日韩精品| 日本伊人精品一区二区三区介绍| 国产精品九九九| 亚洲成年人影院在线| 欧美另类在线播放| 欧美黄色www| 久久手机精品视频| 永久免费毛片在线播放不卡| 午夜精品久久久久久久男人的天堂| 欧美国产第二页| 美日韩精品免费观看视频| 国产亚洲欧美日韩一区二区|