感謝鴻神大大提供的資料,本想直接轉載的,後來發現有些東西弄的不是太清楚,所以就直接自己總結吧,有興趣的可以自己看下鴻神的 blog,我這裏就不講 Executor 這塊的知識了,我又沒弄懂,講出來也是直接 copy 過來的,沒意思。
進入正題,可能現在大多數人還是在使用 Thread + Handler 來處理線程,或者直接線程池處理,其實我也是這樣,畢竟理解起來簡單,而且代碼也容易寫(相對於 AsyncTask),如果使用 AsyncTask,我們怎麼做呢?
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
addAsyncTaskText()
}
fun addAsyncTaskText() {
MyAsyncTaskText("aaaaaaaaaaa").execute("")
}
companion object {
open class MyAsyncTaskText(var content: String) : AsyncTask<String, Int, String>() {
/**
* 準備工作 運行在主線程
*/
override fun onPreExecute() {
super.onPreExecute()
}
/**
* 運行在線程中
*/
override fun doInBackground(vararg params: String?): String {
return content
}
/**
* 運行在主線程
*/
override fun onProgressUpdate(vararg values: Int?) {
super.onProgressUpdate(*values)
}
/**
* 運行在主線程 返回值
*/
override fun onPostExecute(result: String?) {
super.onPostExecute(result)
}
}
}
當時第一次用的時候,對於 onPreExecute、doInBackground、onProgressUpdate 和 onPostExecute 這四個方法,哪個運行在主線程可以更新 UI,哪個運行在子線程,不能做 UI 操作(請不要較真,謝謝),我只能死記硬背,時隔多年,正好閒着沒事幹,就準備研究下它的源碼。
源碼解析
既然有 AsyncTask 的執行方法,那我們先從它的執行方法來看,
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
繼續往下找,來看 executeOnExecutor 方法:
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();
mWorker.mParams = params;
exec.execute(mFuture);
return this;
}
代碼不多,但是涉及到了好多內容,我們一個一個的來解析,先來看下這個方法用啥用,根據官方註解來看下:
通過這個方法我們可以自定義 AsyncTask 的執行方式,串行 or 並行,甚至可以採用自己的 Executor 爲了實現並行,我們可以在外部這麼用 AsyncTask:asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, Params... params); 必須在UI線程調用此方法。
原來如此,這個方法可以用來串行或者並行,使用 AsyncTask 比較多的讀者應該知道,在 Android 3.0 以前,AsyncTask 是並行的,而在 Android 3.0 以後包含 Android 3.0,AsyncTask 是串行的,那麼難道真的沒有辦法在 Android 3.0 以後讓 AsyncTask 並行開發嗎,並不是,後面會講解,如何實現讓 AsyncTask 並行執行。
我們繼續看 executeOnExecutor 源碼,我們來看下第 15 行,先來說下這個狀態,它是 AsyncTask 中的一個枚舉類:
public enum Status {
/**
* 任務等待執行
*/
PENDING,
/**
* 任務已經執行
*/
RUNNING,
/**
* 任務已經執行結束
*/
FINISHED,
}
我們看到第 17 行執行的是 onPreExecute 方法,而在 Android 3.0 以後到 Android 4.0.1 以前,executeOnExecutor 是執行在主線程的,而在 Android 4.0.1 以後,AsyncTask 是可以在子線程實例化的。
1. WorkerRunnable
繼續往下看第 19 行,我們發現有一個 mWorker 出現了,那麼它是什麼呢,我們來看下 AsyncTask 的構造函數:
public AsyncTask(@Nullable Looper callbackLooper) {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Result result = null;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
postResult(result);
}
return result;
}
};
}
我們發現 AsyncTask 的構造函數實例化了一個 WorkerRunnable 類,並重寫了 WorkerRunnable 的 call 方法,那麼 WorkerRunnable 到底是個什麼呢,我們繼續往下看:
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
}
它只是用來接收我們傳遞給 AsyncTask 數據的一個類。
在構造方法中,在 call 方法中,調用了我們最熟悉的 doInBackground 方法,然後執行了 postResult 方法,來看下這個方法:
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
哈哈,熟悉的代碼,忽然找到了親切感,原來是這樣,線程想更新 UI,始終擺脫不了 Handler 啊,那麼我們就來找到這個 Handler:
private static class InternalHandler extends Handler {
public InternalHandler(Looper looper) {
super(looper);
}
@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;
}
}
}
我們來看下 switch 這段代碼,第一個 case 的值正好對應 postResult 方法中發送的值啊,那就來看下 finish 方法唄,
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
好嘛,這裏進行了一次判斷,是否被取消,取消調用 onCancelled,否則調用 onPostExecute,還記得 AsyncTask 構造中 try ... catch 中拋出的異常嗎?
mCancelled.set(true);
通過 finish 方法,我們知道它是運行在主線程的,並且裏邊調用了 onPostExecute,也就說明了 onPostExecute 運行在主線程了。最後把狀態設置成 FINISHED 狀態。
2. FutureTask
看完了 WorkerRunnable,我們繼續來看下一個重點,FutureTask,繼續來看 AsyncTask 的構造:
public AsyncTask(@Nullable Looper callbackLooper) {
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 occurred while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
}
只執行了一個方法 postResultIfNotInvoked,那麼它到底有什麼用呢?其實啊,postResultIfNotInvoked 的中的那個 get 方法獲取的就是 mWorker 中的那個 Result 值,來看下 postResultIfNotInvoked 方法:
private void postResultIfNotInvoked(Result result) {
final boolean wasTaskInvoked = mTaskInvoked.get();
if (!wasTaskInvoked) {
postResult(result);
}
}
如果 wasTaskInvoked 爲 false,則執行 postResult,但是在 AsyncTask 的構造中,wasTaskInvoked 就已經被設置爲了 true,
public AsyncTask(@Nullable Looper callbackLooper) {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Result result = null;
...
return result;
}
};
}
所以呢,這裏的 postResult 一般不會執行,具體什麼時候執行呢,我在研究下。
還有一個方法沒有說到,這裏來說下,在 doInBackground 中執行了我們需要講解的方法,onProgressUpdate 方法:
@Override
protected ReusableBitmap doInBackground(Void... params) {
// enqueue the 'onDecodeBegin' signal on the main thread
publishProgress();
return decode();
}
我們來看下 publishProgress 方法:
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}
還記得我們那個 Handler 的 switch 嗎?我們只說了第一個 case ,我們來看第二個 case:
private static class InternalHandler extends Handler {
public InternalHandler(Looper looper) {
super(looper);
}
@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;
}
}
}
在第二個 case 中,執行了我們可以重寫的 onProgressUpdate 方法,這也是爲什麼他可以做進度條的原因了。
並行執行
在上邊我給出的例子只是串行執行的,那麼在 Android 3.0 及以後怎麼並行執行呢,其實呢,也很簡單,我們只需要調用 AsyncTask 的 executeOnExecutor 方法而不是 execute 就可以了啊。
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
addAsyncTaskText()
}
fun addAsyncTaskText() {
MyAsyncTaskText("aaaaaaaaaaa").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"")
}
companion object {
open class MyAsyncTaskText(var content: String) : AsyncTask<String, Int, String>() {
/**
* 準備工作 運行在主線程
*/
override fun onPreExecute() {
super.onPreExecute()
}
/**
* 運行在線程中
*/
override fun doInBackground(vararg params: String?): String {
return content
}
/**
* 運行在主線程
*/
override fun onProgressUpdate(vararg values: Int?) {
super.onProgressUpdate(*values)
}
/**
* 運行在主線程 返回值
*/
override fun onPostExecute(result: String?) {
super.onPostExecute(result)
}
}
}
好了,關於 AsyncTask 的源碼已經分析完了,有錯的地方請指出,謝謝!!