AsyncTask內部原理

2021-08-21 20:37:53 字數 3637 閱讀 5953

asynctask 是乙個封裝了 threadpoolexecutor 和 handler 機制的抽象類,其作用是方便開發者進行多個非同步任務時無需手動在每個執行緒中都採用 handler 機制來通知 ui 執行緒進行操作, 從而簡化了多個非同步任務與 ui 執行緒的通訊的情況.

我們先留下幾個問題, 在後續的原始碼探索的過程中進行驗證:

下面從這兩個過程,分別從原始碼的角度探索 asynctask 的執行流程和內部原理:

無論在主線程中呼叫到哪個構造方法, 最終都會呼叫到 這個 構造方法,

原始碼如下:

public asynctask(@nullable looper callbacklooper)  catch (throwable tr)  finally 

return result;}};

mfuture = new futuretask(mworker) catch (interruptedexception e) catch (executionexception e) catch (cancellationexception e) }};

}

其中 workerrunnable 是 asynctask 乙個內部類,原始碼如下:

private static abstract class workerrunnableimplements callable
execute 方法會呼叫到 executeonexecutor 方法, 

原始碼如下:

public final asynctaskexecute(params... params)
@mainthread

public final asynctaskexecuteonexecutor(executor exec,

params... params)

}mstatus = status.running;

onpreexecute(); // 注意此處呼叫了 onpreexecute

mworker.mparams = params; // 注意此處把傳入的 params 賦值給了 mparams

exec.execute(mfuture); // 1

return this;

}

我們看到, 當我們呼叫到 execute 方法後, 最終會用到 exec 這個變數執行之前在構造方法中初始化好的 future 物件, 我們跟進看看這個 exec 是什麼:

private static volatile executor sdefaultexecutor = serial_executor;
/**

* an that executes tasks one at a time in serial

* order. this serialization is global to a particular process.

*/public static final executor serial_executor = new serialexecutor();

到了這裡我們明白了,  exec 就是乙個 serialexecutor, 官方也明確的描述到了, 對於乙個程序來說, 這個 asynctask 會序列執行所有提交的任務, 接下來, 我們看看 它的 execute 方法的實現:

private static class serialexecutor implements executor  finally 

}});

if (mactive == null)

}protected synchronized void schedulenext()

}}

我們可以看到, 這個 serialexecutor 的實現其實很簡單, 其 execute 方法會把傳入的 runnable 物件壓入雙向佇列,  然後判斷當前有沒有正在執行的任務, 如果沒有直接呼叫 schedulenext 來開始執行乙個任務, 然後真正執行任務的是由 thread_pool_executor , 這是乙個自定義的執行緒池, 會根據裝置的 cpu 數量設定核心池執行緒的數量, 到了這裡我們可以解釋一下為什麼 3.0 之後的 asynctask 是序列執行任務的了:

接下來我們看看在執行的過成中和 主線程 進行通訊的細節:

前面我們看到, 在 構造方法中會把 doinbackground 包裝在乙個 worker  中, 然後傳入到了 futuretask 中, 然後再把 futuretask 傳給了 exce 的 execute 的方法進行排隊執行,  因此我們再看看 worker 的實現:

mworker = new workerrunnable()  catch (throwable tr)  finally 

return result;

}

我們看到, 無論如何最後都會執行到 finally 中的 postresult, 跟進看看:

private result postresult(result result)
很明顯, 這裡是獲取 handler 給主線程傳送訊息, 我們看看這個 gethandler 是什麼:

private handler gethandler()
讀者還記不記得這個 handler 是在 構造方法中進行的初始化:

/**

* creates a new asynchronous task. this constructor must be invoked on the ui thread.

** @hide

*/public asynctask(@nullable looper callbacklooper)

return shandler; // 靜態成員變數

}}

跟進看看這個 internalhandler 是什麼:

private static class internalhandler extends handler 

@suppresswarnings()

@override

public void handlemessage(message msg)

}}

到了這裡, 我們可以解釋為什麼 asynctask 必須要在主線程中進行初始化了:

接下來, 我們看到之前由 postrresult 傳送的 message_post_result 訊息在這裡得到了處理, 這個 task 便是傳入的 this, 也就是 asynctask 例項物件, 我們看看 finish 方法:

private void finish(result result)  else 

mstatus = status.finished;

}

很簡單, 判斷是否取消, 否則就呼叫 onpostexecute 方法進行最後的收尾工作, 我們可以對其進行重寫.

我們通過對原始碼的探索, 解答了開頭留下的兩個問題:

AsyncTask原理淺見

asynctask的基原理是建立乙個執行緒池,通過執行緒池執行乙個runnable物件 futuretask 然後通過handler通知ui執行緒。1 執行緒池的建立。建立執行緒池,並返回乙個執行器物件 executor private static final int core pool size...

AsyncTask實現原理

asynctask是android提供的輕量級的非同步類,可以直接繼承asynctask,在類中實現非同步操作,並提供介面反饋當前非同步執行的程度 可以通過介面實現ui進度更新 最後反饋執行的結果給ui主線程 使用的優點 簡單,快捷,過程可控 ui的更新只能在主線程中完成。asynctask定義了三...

AsyncTask的工作原理

在1.6之前,asynctask是序列執行任務的,1.6的時候asynctask開始採用執行緒池裡處理並行任務,但是從3.0開始,為了避免asynctask所帶來的併發錯誤,asynctask又採用乙個執行緒來序列執行任務。具體執行流程,通過原始碼來分析 public asynctask catch...