又是新的一年的开始,近几年除了时不时的外包项目,剩下的大部分空闲时间都给了腾讯手游。
AsyncTask这东西,现在APP开发中估计早已经被废弃掉,但内部实现还是值得去学习(要不然怎么好意思说你做了几年安卓开发),另外找工作时一些面试大佬偶尔也会问到AsyncTask内部原理或者间接的让你说一说它的缺点。
今天主要解惑一下
1.AsyncTask是怎么将子线程中执行的结果返回给主线程
2.平时提交的任务线程是并行执行还是按照先后单个任务依次执行
3.为什么提交的任务数到等待队列超过128会抛异常
public abstract class AsyncTask
class MyAsyncTask extends AsyncTask {
@Override
protected void onPreExecute() {
//主线程中执行,任务开始前
}
@Override
protected Result doInBackground(String... strings) {
//在子线程中执行任务并且将执行结果返回主线程
}
@Override
protected void onProgressUpdate(Integer... values) {
//回调主线程更新当前进度
}
@Override
protected void onPostExecute(Result result) {
//执行结果result回调主线程
}
@Override
protected void onCancelled() {
//任务被取消
}
}
FutureTask跟Callable。这里有一个介绍 https://www.cnblogs.com/fengsehng/p/6048609.html
public AsyncTask() {
this((Looper) null);
}
public AsyncTask(@Nullable Handler handler) {
this(handler != null ? handler.getLooper() : null);
}
public AsyncTask(@Nullable Looper callbackLooper) {
//初始UI Handler(Handler主要用来线程间通信,可以思考一下是不是Handler把执行结果从子线程传递给了UI线程)
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
? getMainHandler()
: new Handler(callbackLooper);
//初始化WorkerRunnable,实际是一个实现Callable接口的类.
mWorker = new WorkerRunnable() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Result result = null;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//此处留意一下doInBackground,它在什么时候回执行到这里
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
//此处稍后看看究竟
postResult(result);
}
return result;
}
};
//初始化一个FutureTask,将mWork引用(先稍微留意一下mFuture)
mFuture = new FutureTask(mWorker) {
@Override
protected void done() {
//...
}
};
}
public final AsyncTask execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
public final AsyncTask executeOnExecutor(Executor exec,
Params... params) {
//看到这里会不是想起平时一个AsyncTask实例多次调用execute会抛出异常,这里就是原因
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;
//在构造方法中实例的FutureTask当做参数给到了exec这个实例,接下来看看exec里面对FutureTask做了什么
exec.execute(mFuture);
return this;
}
//exec实例,跟进去会发现其实就是这个
private static class SerialExecutor implements Executor {
final ArrayDeque mTasks = new ArrayDeque();
Runnable mActive;
//参数Runnable其实就是刚刚传进来的那个FutureTask实例
//该方法里面重新实例了一个Runnable,并将Runable放进mTasks队列中
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
//执行完一个FutureTask会从mTasks取出下一个Runnable交给线程池。
//此处可以知道,多个任务会加入队列中,依次执行任务。多任务不是并列执行
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
//此实例是一个自定义的线程池,下面再看看这个实现
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
//看到这里,是不是知道AsyncTask线程任务的等待队列数超过128会抛出异常原因
private static final BlockingQueue sPoolWorkQueue =
new LinkedBlockingQueue(128);
static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}
刚刚在AsyncTask构造方法注意到postResult,看看postResult内部实现,就会发现它是使用Handler将直接结果发给你了UI线程
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult(this, result));
message.sendToTarget();
return result;
}
//再看看getHandler中handMessage
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:
// 这里将任务的结果给到了UI线程,mTask其实就是AsyncTask实例,再看finish
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
//这里对结果进行了回调,也是平时我们开发中的结果处理实现
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
仔细观看内部实现其实也没有什么神奇的,记得找工作时就遇到过几次被问到关于AsyncTask,最近工作时间宽松,决定把分析源码成果写上博客,以来自己可以加深一次记忆而来给大家分享一下成果