感谢鸿神大大提供的资料,本想直接转载的,后来发现有些东西弄的不是太清楚,所以就直接自己总结吧,有兴趣的可以自己看下鸿神的 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 的源码已经分析完了,有错的地方请指出,谢谢!!