1,简介:
AsyncTask允许正确且容易地使用UI线程。该类允许您在UI线程上执行后台操作并发布结果,而无需操作thread或者handler。
AsyncTask被设计成一个围绕thread和handler程序的帮助类,而不是一个通用的线程框架。异步任务理想情况下应该用于短操作(最多几秒钟)。如果您需要让线程长时间运行,强烈建议您使用 java.util.concurrent提供的各种并发api,如Executor、ThreadPoolExecutor和FutureTask。
AsyncTask由在后台线程上运行的计算定义,其结果在UI线程上发布。AsyncTask由3种泛型类型(称为Params、Progress和Result)和4个步骤(称为onPreExecute、doInBackground、onProgressUpdate和onPostExecute)定义。
AsyncTask是基于 java.util.concurrent包中的ThreadPoolExecutor实现的线程池。默认是串行执行的,但也可以并行。
2,使用
2.1覆盖4个方法。
public class LoadingTask extends AsyncTask {
@Override
protected void onPreExecute() {
super.onPreExecute();
//UI线程 准备逻辑
}
@Override
protected Byte[] doInBackground(String... strings) {
//工作线程 实现耗时逻辑
return new Byte[0];
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
//UI线程 进度更新通知
}
@Override
protected void onPostExecute(Byte[] bytes) {
super.onPostExecute(bytes);
//UI线程 结果
}
}
2.2执行代码
//并发执行
new LoadingTask().executeOnExecutor(LoadingTask.THREAD_POOL_EXECUTOR,"loadingUrl");
//默认串行执行
new LoadingTask().execute("loadingUrl");
3.构造方法
3.1不带参数的构造方法调用带参数的构造方法。
new LoadingTask() 默认调用父类AsyncTask不带参数的构造方法。
/**
* 创建一个异步任务,这个构造方法必须在UI线程中调用。
*/
public AsyncTask() {
this((Looper) null);
}
3.2带参数的构造方法。
AsyncTask空的构造方法又调用了,带一个参数(Looper)的构造方法,并且传入了null。
/**
* 创建一个异步任务,这个构造方法必须在UI线程中调用。
*/
public AsyncTask(@Nullable Looper callbackLooper) {
//给mHandler赋UI线程Handler值
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
? getMainHandler()
: new Handler(callbackLooper);
//初始化工作任务
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;
}
};
mFuture = new FutureTask(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);
}
}
};
}
3.3 WorkerRunnable抽象类的源码与解释。
/**
* 基于返回结果Result并可能引发异常的任务Callabe。
* 子类实现WorkerRunnable需要实现了一个没有参数调用的方法call。
* Callable类似于Runnable,因为它们都是为实例可能由另一个线程执行的类设计的。然而,Runnable不返回结果,也不能抛出检查过的异常。
* Executors类包含实用程序方法,用于从其他公共表单转换为可调用类。
*
* @param
* @param
*/
private static abstract class WorkerRunnable implements Callable {
/**
* 传入doInBackground方法的参数
*/
Params[] mParams;
}
3.4 mFuture的定义与解释。
/**
* 可取消的异步计算。
* FutureTask提供了Future的基本实现,提供了启动和取消计算、查询计算是否完成以及检索计算结果的方法。
* 计算完成后才能检索结果;如果计算尚未完成,get方法将阻塞。一旦计算完成,就不能重新启动或取消计算(除非使用runAndReset调用计算)。
* FutureTask可以用来包装一个可调用或可运行的对象。因为FutureTask实现了Runnable,所以FutureTask可以提交给执行程序执行。
* 除了作为独立类使用之外,FutureTask还提供了在创建定制任务类时可能有用的受保护功能。
*/
private final FutureTask mFuture;
4 串行执行
AsyncTask默认是串行执行的。
execute方法也是调用的executeOnExecutor方法。传入的是sDefaultExecutor
@MainThread
public final MyAsyncTask execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
串行线程池的sDefaultExecutor的实现:
/**
* 串行执行线程池。
*/
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
SERIAL_EXECUTOR的定义:
/**
* 一个{@link Executor},按串行顺序一次执行一个任务。这种序列化对于特定的流程是全局的。
*/
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
SerialExecutor是串行执行的,这也是AsyncTask的默认行为。
/**
* 串行Executor,基于THREAD_POOL_EXECUTOR实现串行
*/
private static class SerialExecutor implements Executor {
/**
* 串行任务的双端队列
*/
final ArrayDeque mTasks = new ArrayDeque();
Runnable mActive;
@Override
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
@Override
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);
}
}
}
5 平行执行
THREAD_POOL_EXECUTOR定义与解释
/**
* cup个数
*/
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
/**
* 核心线程数
* 我们希望在核心池中至少有2个线程,最多4个线程,希望比CPU计数少1个线程,以避免后台工作占用CPU
*/
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;
/**
* alive时间 30s
*/
private static final int KEEP_ALIVE_SECONDS = 30;
/**
* 根据需要创建新线程的对象。
* 使用线程工厂可以删除对新线程的硬连接调用,
* 使应用程序能够使用特殊的线程子类、优先级等。
*/
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "MyAsyncTask #" + mCount.getAndIncrement());
}
};
/**
* 任务队列,容量128个
*/
private static final BlockingQueue sPoolWorkQueue =
new LinkedBlockingQueue(128);
/**
* An {@link Executor} 并行执行的线程池.
*/
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, new ThreadPoolExecutor.DiscardOldestPolicy());
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}
executeOnExecutor方法。executeOnExecutor方法允许你指定任务是串行还是并行执行的Executor,
传入使用THREAD_POOL_EXECUTOR,并行执行。
传入使用SERIAL_EXECUTOR,串行执行。
执行前调用了onPreExecute方法。
@MainThread
public final MyAsyncTask 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;
}
6 post结果
mFuture = new FutureTask(mWorker) {
/**
* 任务结束后调用改方法
*/
@Override
protected void done() {
try {
//调用get获取结果,并分发。
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);
}
}
};
解释再多,不如直接看源码来的直接。从源码可以看出,task执行完以后会调用postResultIfNotInvoked(Result result),传入的结果是get方法返回的。
再看看postResultIfNotInvoked的源码
/**
* 分发结果
*
* @param result
*/
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(this, result));
message.sendToTarget();
return result;
}
可以看出,postResultIfNotInvoked方法调用了postResult方法。最终通过Handler给UI线程发送了Message,告知了Result结果。
7 onProgressUpdate方法何时触发
当后台task仍在运行时,可以从doInBackground调用publishProgress方法在UI线程上发布更新。
对这个方法的每次调用都会触发UI线程上onProgressUpdate的执行。 如果任务已被取消,则不会调用onProgressUpdate。
@WorkerThread
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult
很简单吧。