【Android 异步操作】AsyncTask 异步任务 ( AsyncTask 异步任务执行方法 execute 方法相关源码解析 )
文章目錄
- 一、AsyncTask 異步任務執行方法 execute() 引入
- 二、AsyncTask 異步任務執行方法 execute()
- 三、sDefaultExecutor 線程池解析
- 四、executeOnExecutor 方法解析
- 五、AsyncTask 異步任務執行方法 execute() 相關源碼注釋
一、AsyncTask 異步任務執行方法 execute() 引入
上一篇博客中 【Android 異步操作】AsyncTask 異步任務 ( 參數簡介 | 方法簡介 | 使用方法 | AsyncTask 源碼分析 ) , 講解了 AsyncTask<Params, Progress, Result> 異步任務的構造函數 ;
異步任務執行有兩個方法 :
- 構造異步任務 : 調用 AsyncTask 的構造函數 , 創建 AsyncTask 異步任務對象 ;
- 執行異步任務 : 調用 AsyncTask 異步任務對象的 execute() 方法 , 執行異步任務 ;
本篇博客中講解執行函數 AsyncTask<Params, Progress, Result> execute(Params… params) ;
// 1. 創建 AsyncTask 異步任務 MyAsyncTask mMyAsyncTask = new MyAsyncTask();// 2. 執行 AsyncTask 異步任務 mMyAsyncTask.execute();二、AsyncTask 異步任務執行方法 execute()
AsyncTask<Params, Progress, Result> execute(Params… params) 方法作用 : AsyncTask 異步任務的 execute() 函數作用就是提交任務 , 其提交的任務就是 FutureTask , 其使用的是 線程池 提交任務 ;
① 參數 : 使用指定的參數 , 執行任務 ;
② 返回值 : 這個任務返回 AsyncTask<Params, Progress, Result> 本身對象 , 以便調用者可以持有該異步任務的引用 ;
③ 任務調度 : 該方法在隊列上調度一個任務 , 該任務在一個單獨的后臺線程 , 或線程池中執行 ; 第一次引入后 , 異步任務在單獨后臺線程中被串行執行 ;
④ 不同版本的執行任務載體 :
- Android 1.6(API 級別 4)及以下的版本是在一個后臺線程中串行執行 ;
- Android 2.0(API 級別 5)及以上的版本是在線程池中串行執行 ;
- Android 3.0(API 級別 11)及以上的版本有回復到在一個后臺線程中串行執行 ;
在該類中 , 最終調用了 executeOnExecutor() 方法 , 使用 sDefaultExecutor 默認串行線程池執行任務 ;
public abstract class AsyncTask<Params, Progress, Result> {@MainThreadpublic final AsyncTask<Params, Progress, Result> execute(Params... params) {return executeOnExecutor(sDefaultExecutor, params);} }如果同時調用 AsyncTask 異步任務的 execute() 函數執行任務 , 其任務會逐個串行執行 , 不是并行的 ;
AsyncTask<Params, Progress, Result> 對象的 execute() 執行的任務是有序的 ;
三、sDefaultExecutor 線程池解析
上述執行異步任務的方法 executeOnExecutor() , 傳入了 sDefaultExecutor 線程池作為參數 , 本節分析 sDefaultExecutor 線程池 ;
sDefaultExecutor 是成員變量 , 其聲明類型是 Executor , 實際類型是自定義的線程池 SerialExecutor() ;
SerialExecutor 是一個線程池 , 執行任務 , 每次只執行一個任務 , 按照串行順序執行 ; 該序列對于特定進程來說是全局的 , 即一個進程只有一個該序列 ;
在該線程池中 , 維護了如下兩個成員 :
- 任務隊列 ArrayDeque mTasks
- 當前執行任務 Runnable mActive
該線程池中 void execute(final Runnable r) 執行任務方法 :
- 執行當前傳入的任務 : 自己創建一個 Runnable , 在其 run() 方法中執行傳入的參數的 r 的 run() 方法 ;
- 執行下一個任務 : 執行完畢當前任務后 , 調用 scheduleNext() 執行下一個任務
scheduleNext() 方法 用于執行下一個任務 , 從隊列中取出一個任務 , 如果取出的任務不為空 , 那么就執行該任務 ; 調用 SerialExecutor 類的 execute(final Runnable r) 方法執行該任務 ;
public abstract class AsyncTask<Params, Progress, Result> {private static final String LOG_TAG = "AsyncTask";/*** 自定義線程池 ; * 一個線程池 , 執行任務 , 每次只執行一個任務 , 按照串行順序執行 ; * 該序列對于特定進程來說是全局的 , 即一個進程只有一個該序列 ; */public static final Executor SERIAL_EXECUTOR = new SerialExecutor();@UnsupportedAppUsageprivate static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;/*** 自定義線程池 ; * 一個線程池 , 執行任務 , 每次只執行一個任務 , 按照串行順序執行 ; * 該序列對于特定進程來說是全局的 , 即一個進程只有一個該序列 ; */private static class SerialExecutor implements Executor {// 任務隊列 final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();// 當前執行的任務 Runnable mActive;// 執行任務public synchronized void execute(final Runnable r) {// 自己創建一個 Runnable , 在其 run() 方法中執行如下方法 : // 傳入的 execute(final Runnable r) 方法參數的 r 的 run() 方法 ; mTasks.offer(new Runnable() {public void run() {try {r.run();} finally {// 執行完畢當前任務后 , 執行下一個任務scheduleNext();}}});// 如果當前任務為空 , 那么執行下一個任務 if (mActive == null) {scheduleNext();}}/*** 執行下一個任務 * 從隊列中取出一個任務 , 如果取出的任務不為空 , 那么就執行該任務 ; * 調用 SerialExecutor 類的 execute(final Runnable r) 方法執行該任務 ; */protected synchronized void scheduleNext() {if ((mActive = mTasks.poll()) != null) {// 執行隊列中的任務的操作 THREAD_POOL_EXECUTOR.execute(mActive);}}} }四、executeOnExecutor 方法解析
executeOnExecutor 方法是異步任務執行的核心方法 ;
執行流程如下 :
① 判定合法性 : AsyncTask 異步任務只能執行一次 , 必須確保該 AsyncTask 異步任務沒有執行過 , 如果執行過直接拋出異常 ;
② 設置運行狀態 : 將該異步任務狀態設置成 Status.RUNNING 狀態 , 防止第二次被執行 ;
③ 主線程初始化 : 執行 onPreExecute() 方法 , 用戶可以在該方法中初始化 UI , 該操作在 UI 主線程中運行 ;
④ 子線程后臺任務執行 : 執行 FutureTask 中的 Callable 任務 , 也就是異步任務 , 該操作在子線程中運行 ;
public abstract class AsyncTask<Params, Progress, Result> { /*** 使用指定的參數 , 執行任務 ; * 這個任務返回 AsyncTask<Params, Progress, Result> 本身對象 , * 一遍調用者可以持有該異步任務的引用 ; * * 該方法通常與 THREAD_POOL_EXECUTOR 一同使用 , 允許多個任務在一個線程池中串行執行 , * 該線程池由 AsyncTask 異步任務管理 , 也可以使用自己的線程池定制相關行為 ; */@MainThreadpublic final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,Params... params) {// 首先判定當前狀態是否合法 , 確保該 AsyncTask 異步任務沒有執行過 , // 每個 AsyncTask 異步任務創建后只能執行一次 ; 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;// 執行 doInBackground() 之前執行的方法 onPreExecute();// 設置 WorkerRunnable 的 Params[] mParams 參數mWorker.mParams = params;// 執行 FutureTask 中的 Callable 任務exec.execute(mFuture);return this;}}
五、AsyncTask 異步任務執行方法 execute() 相關源碼注釋
public abstract class AsyncTask<Params, Progress, Result> {private static final String LOG_TAG = "AsyncTask";/*** 自定義線程池 ; * 一個線程池 , 執行任務 , 每次只執行一個任務 , 按照串行順序執行 ; * 該序列對于特定進程來說是全局的 , 即一個進程只有一個該序列 ; */public static final Executor SERIAL_EXECUTOR = new SerialExecutor();@UnsupportedAppUsageprivate static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;/*** 自定義線程池 ; * 一個線程池 , 執行任務 , 每次只執行一個任務 , 按照串行順序執行 ; * 該序列對于特定進程來說是全局的 , 即一個進程只有一個該序列 ; */private static class SerialExecutor implements Executor {// 任務隊列 final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();// 當前執行的任務 Runnable mActive;// 執行任務public synchronized void execute(final Runnable r) {// 自己創建一個 Runnable , 在其 run() 方法中執行如下方法 : // 傳入的 execute(final Runnable r) 方法參數的 r 的 run() 方法 ; mTasks.offer(new Runnable() {public void run() {try {r.run();} finally {// 執行完畢當前任務后 , 執行下一個任務scheduleNext();}}});// 如果當前任務為空 , 那么執行下一個任務 if (mActive == null) {scheduleNext();}}/*** 執行下一個任務 * 從隊列中取出一個任務 , 如果取出的任務不為空 , 那么就執行該任務 ; * 調用 SerialExecutor 類的 execute(final Runnable r) 方法執行該任務 ; */protected synchronized void scheduleNext() {if ((mActive = mTasks.poll()) != null) {// 執行隊列中的任務的操作 THREAD_POOL_EXECUTOR.execute(mActive);}}}/*** 使用指定的參數 , 執行任務 ; * 這個任務返回 AsyncTask<Params, Progress, Result> 本身對象 , * 一遍調用者可以持有該異步任務的引用 ; * * 該方法在隊列上調度一個任務 , 該任務在一個單獨的后臺線程 , 或線程池中執行 ; * 第一次引入后 , 異步任務在單獨后臺線程中被串行執行 ; * Android 1.6(API 級別 4)及以下的版本是在一個后臺線程中串行執行 ; * Android 2.0(API 級別 5)及以上的版本是在線程池中串行執行 ; * Android 3.0(API 級別 11)及以上的版本有回復到在一個后臺線程中串行執行 ; ** <p>改方法必須在 UI 線程中調用 ** @param 要執行的任務的參數.** @return 返回異步任務 AsyncTask 本身 .*/@MainThreadpublic final AsyncTask<Params, Progress, Result> execute(Params... params) {return executeOnExecutor(sDefaultExecutor, params);}/*** 使用指定的參數 , 執行任務 ; * 這個任務返回 AsyncTask<Params, Progress, Result> 本身對象 , * 一遍調用者可以持有該異步任務的引用 ; * * 該方法通常與 THREAD_POOL_EXECUTOR 一同使用 , 允許多個任務在一個線程池中串行執行 , * 該線程池由 AsyncTask 異步任務管理 , 也可以使用自己的線程池定制相關行為 ; */@MainThreadpublic final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,Params... params) {// 首先判定當前狀態是否合法 , 確保該 AsyncTask 異步任務沒有執行過 , // 每個 AsyncTask 異步任務創建后只能執行一次 ; 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;// 執行 doInBackground() 之前執行的方法 onPreExecute();// 設置 WorkerRunnable 的 Params[] mParams 參數mWorker.mParams = params;// 執行 FutureTask 中的 Callable 任務exec.execute(mFuture);return this;}}
總結
以上是生活随笔為你收集整理的【Android 异步操作】AsyncTask 异步任务 ( AsyncTask 异步任务执行方法 execute 方法相关源码解析 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Android 异步操作】AsyncT
- 下一篇: 【Android 异步操作】AsyncT