一、AsyncTask简介
AsyncTask是Android提供的一个轻量级异步任务机制,使用AsyncTask可以方便的执行异步任务,并将结果更新到main thread。AsyncTask中是通过Handler机制来让work thread和main thread通信的。
二、AsyncTask使用
AsyncTask有三个泛型参数,分别是Params, Progress, Result。Params是指后台任务运行的参数,用于在doInBackground使用,Progress是用来指示后台任务执行进度的单位,Result是后台任务的返回结果,在doInBackground方法中返回,交给onPostExecute处理。这些参数不需要时可以用Void代替。
public class TestAsyncTask extends AsyncTask<Void, Integer, Void> {
private String taskName;
public TestAsyncTask(String name) {
super();
taskName = name;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
// onPreExecute在doInBackground之前执行,用于执行准备工作
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
// onProgressUpdate用来更新后台任务的执行进度。
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
// onPostExecute做一些更新UI的操作
Log.v("stone", "task = " + taskName + " onPostExecute in " + Thread.currentThread().toString());
}
@Override
protected Void doInBackground(Void... params) {
// 只有doInBackground是运行在workthread中的.其他方法运行在主线程
// 耗时的操作放在doInBackground进行
Log.v("stone", "task = " + taskName + " doInBackground in " + Thread.currentThread().toString());
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.toString();
}
return null;
}
}
//AsyncTask的两种启动方式
new TestAsyncTask("task_" + i).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
new TestAsyncTask("tasktesk_" + i).execute();
三、AsyncTask源码分析
1、AsyncTask构造初始化
public AsyncTask(@Nullable Looper callbackLooper) {
// 创建Handler
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
? getMainHandler()
: new Handler(callbackLooper);
// 初始化Callable 回调使用
mWorker = new WorkerRunnable<Params, Result>() {
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;
}
};
// Runable 线程池真正执行的对象
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);
}
}
};
}
构造方法主要初始化
Handler:发送消息
mWorker: 会在回调call() 方法中调用 doInBackground()
mFuture :会交给Executor去执行
2、AsyncTask 执行
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
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()方法,这就解释了为什么onPreExecute方法是最新被调用的
onPreExecute();
mWorker.mParams = params;
exec.execute(mFuture);
return this;
}
把mFuture交给我们传入的Executor来执行。对面我们前文提到了AsyncTask的两种启动方式,他们执行方式的不同是因为传入的Executor不同导致的。我们前面提到过execute方法传给executeOnExecutor的是一个sDefaultExecutor对象,通过源码来看一下sDefaultExecutor是什么:
// AsyncTask中的静态内部类
private static class SerialExecutor implements Executor {
// AsyncTask 任务栈队列
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
public synchronized void execute(final Runnable r) {
// 添加一个 AsyncTask
mTasks.offer(new Runnable() {
public void run() {
try {
// 这里的 r就是 mFuture
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
// 取出一个 Runnable 执行
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
SerialExecutor 是一个静态内部类,内部维护 ArrayDeque mTasks 队列,通过execute(final Runnable r) 将AsyncTask添加到mTasks( mTasks.offer())中,之后通过mTask.poll() 方法取出交给 线程池执行THREAD_POOL_EXECUTOR.execute(mActive)。
线程池回调Runnable(mFuture)的run()方法,而mFuture如何引起mWorker的回调呢?
源码:
// 构造传递callable
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
}
// 线程池execute(Runable)时执行
public void run() {
...
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
// Callable 执行call方法
result = c.call();
ran = true;
} catch (Throwable ex) {
.....
}
} finally {
...
}
}
至此 AsyncTask的执行流程就完成了。
小结:
1、AsyncTask 初始化一个mWorker(Callable) 、一个mFuture(Runable)和创建一个Handler
2、当 AsyncTask 执行execute()方法时,就是mFuture添加offer()到 mTasks 队列中,之后取出poll()交给线程池执行。
3、线程池执行Runable 会回调mWorker 的run方法从而在子线程执行doInBackground()
3、AsyncTask回调
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
// 发送消息
message.sendToTarget();
return result;
}
// Message 类方法
public void sendToTarget() {
target.sendMessage(this);
}
由getHandler()
private Handler getHandler() {
return mHandler;
}
mHandler 如何初始化呢?AsyncTask构造函数中初始化 InternalHandler
public AsyncTask(@Nullable Looper callbackLooper) {
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
? getMainHandler()
: new Handler(callbackLooper);
.....
}
InternalHandler 接收发送的消息
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
// 分发消息 onCancelled 、onPostExecute
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
// 分发消息 onProgressUpdate
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
小结
1、在mWorker中回调执行 postResult(result)
2、postResult将执行的结果通过Handler消息机制发送出去
3、InternalHandler中接收Handler发送的消息,并分发AsyncTask的onCancelled 、onPostExecute、onProgressUpdate方法
4、InternalHandler 通过 sHandler = new InternalHandler(Looper.getMainLooper())创建因此onCancelled 、onPostExecute、onProgressUpdate 等方法运行在主线程
四、AsyncTask运行机制总结
AsyncTask初始化及执行:
1、AsyncTask 初始化一个mWorker(Callable) 、一个mFuture(Runable)和创建一个Handler
2、当 AsyncTask 执行execute()方法时,就是mFuture添加offer()到 mTasks 队列中,之后取出poll()交给线程池执行。
3、线程池执行Runable 会回调mWorker 的run方法从而在子线程执行doInBackground()
AsyncTask执行结果回调:
1、在mWorker中回调执行 postResult(result)
2、postResult将执行的结果通过Handler消息机制发送出去
3、InternalHandler中接收Handler发送的消息,并分发AsyncTask的onCancelled 、onPostExecute、onProgressUpdate方法
4、InternalHandler 通过 sHandler = new InternalHandler(Looper.getMainLooper())创建因此onCancelled 、onPostExecute、onProgressUpdate 等方法运行在主线程
五、AsyncTask不足
AsyncTask是Handler与线程池的封装。
网络请求等耗时操作在线程池中完成,通过handler发送给主线程完成UI更新。
使用线程池的主要原因是避免不必要的创建及销毁线程的开销。
六、线程池属性
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// We want at least 2 threads and at most 4 threads in the core pool,
// preferring to have 1 less than the CPU count to avoid saturating
// the CPU with background work
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE_SECONDS = 30;
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
核心线程数为:最少两个最多4个,最大线程数是2倍的CPU核个数+1,任务排队队列大小为128,