基于 Android-24
AsyncTask 是安卓 sdk 提供的一个异步框架,用来解决耗时任务线程和主线程之间通讯问题。
但是因为 sdk 升级过程中的几次重大改动,导致 AsyncTask 有了很多『坑』
asyncTask_01.png但是不可否认 AsyncTask 框架的设计,还有值得学习的。
AsyncTask 框架
AsyncTask 核心代码只有一个文件,其中包含
3 个静态内部类
1 个静态内部抽象类
1 个枚举类
1 个 AsyncTask 类
asyncTask_03.png
使用方法
new AsyncTask<Object,Object,Object>(){
@Override
protected Object doInBackground(Object[] params) {
return null;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
}
}.execute();
三个泛型参数分别代表:传入参数类型、任务进度单位、返回结果类型
AsyncTask 线程池管理
public static final Executor THREAD_POOL_EXECUTOR;
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;
}
其中:
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// 核心线程数最小为2 ,最大为 4 。根据 cpu 核数确定。
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
// 最大线程数量为 cpu 核数的 2 倍 - 1
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
// 非核心线程数存活时间为 30s
private static final int KEEP_ALIVE_SECONDS = 30;
AsyncTask 创建的线程,都会用 『AsyncTask #』开头标记
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
}
};
AsyncTask 的任务队列长度为 128
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);
关于线程池参数含义参考Java 线程池源码阅读笔记
AsyncTask 任务执行过程
-
execute 方法
AsyncTask 有三个 execute 方法。 1.直接通过内置线程调度器,执行一个 runnable public static void execute(Runnable runnable) 2.使用内置线程调度器,传入参数执行 doInBackground 中的任务。 public final AsyncTask<Params, Progress, Result> execute(Params... params) 3.使用自定义任务调度器,传入参数执行 doInBackground 中的任务。 public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) 其中『第二种』方法,会调用『第三种』方法,不过是将内置的线程调度器传递过去
-
sDefaultExecutor 成员变量
sDefaultExecutor 是一个线性调度器
private static class SerialExecutor implements Executor { final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>(); Runnable mActive; public synchronized void execute(final Runnable r) { mTasks.offer(new Runnable() { public void run() { try { r.run(); } finally { scheduleNext(); } } }); if (mActive == null) { scheduleNext(); } } protected synchronized void scheduleNext() { if ((mActive = mTasks.poll()) != null) { THREAD_POOL_EXECUTOR.execute(mActive); } }
}
SerialExecutor 类有以下几个特点
1. execute 和 scheduleNext 方法都持有一个对像锁。
2. 如果队列 mTasks 不为空,mActive 则不为空。
3. mActive 为空,则表示队列已空,执行 scheduleNext 执行队列刚添加的任务。
4. mActive 不为空,添加任务到队列尾部。等待任务出栈。
流程图大致如下
asyncTask_02.png-
executeOnExecutor() 方法
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) { if (mStatus != Status.PENDING) { …… } mStatus = Status.RUNNING; onPreExecute(); mWorker.mParams = params; exec.execute(mFuture); return this; }
executeOnExecutor 方法中执行了 onPreExecute() ,然后执行 exec.execute(mFuture)。
其中 mFuture 代码如下public AsyncTask() { mWorker = new WorkerRunnable<Params, Result>() { public Result call() throws Exception { mTaskInvoked.set(true); Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); //noinspection unchecked Result result = doInBackground(mParams); Binder.flushPendingCommands(); return postResult(result); } }; mFuture = new FutureTask<Result>(mWorker) { @Override protected void done() { try { postResultIfNotInvoked(get()); } …… } }; }
通过以上代码,可以得出
1. AsyncTask 任务封装到 FutureTask 中。 2. 在执行任务之前先执行 onPreExecute(),此时依旧在主线程。 3. doInBackground() 在线程成中执行。 4. 任务执行完毕会执行 postResult 或者 postResultIfNotInvoked 发送消息给主线程
-
返回结果
private void postResultIfNotInvoked(Result result) { final boolean wasTaskInvoked = mTaskInvoked.get(); if (!wasTaskInvoked) { postResult(result); } } private Result postResult(Result result) { @SuppressWarnings("unchecked") Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result)); message.sendToTarget(); return result; }
通过 postResult 方法返回结果给主线程。
private static Handler getHandler() { synchronized (AsyncTask.class) { if (sHandler == null) { sHandler = new InternalHandler(); } return sHandler; } } private static class InternalHandler extends Handler { public InternalHandler() { super(Looper.getMainLooper()); } @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; } }
最终会调用 finish 方法
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
- 总结 AsyncTask 框架的时序图如下
网友评论