简介
AsynTask方便在后台线程中执行操作,然后将结果发给主线程,从而在主线程更新UI,无需关心Thread和Handler;AsynTask只能执行短暂的后台任务,如果需要执行长时间耗时任务,推荐使用java.util.concurrent包中的ThreadPoolExecutor;使用AsynTask至少要重写doInBackground方法,和经常用来更新UI的onPostExecute方法;AsynTask的内部实现原理是线程池和Handler。
用法
MyAsyncTask myAsyncTask = new MyAsyncTask(tv_update, pro);
myAsyncTask.execute("开始执行");
static class MyAsyncTask extends AsyncTask<String, Integer, String> {
private TextView update;
private ProgressBar pro;
private final String tag;
public MyAsyncTask(TextView update, ProgressBar pro) {
tag = MyAsyncTask.class.getSimpleName();
this.update = update;
this.pro = pro;
}
@Override
protected void onPreExecute() {
update.setText("开始准备执行异步任务");
}
@Override
protected String doInBackground(String... params) {
Log.e(tag, "doInBackground:" + params[0]);
int count = 0;
while (count < 100) {
try {
Thread.sleep(2000);
count += 10;
publishProgress(count);
} catch (InterruptedException e) {
e.getStackTrace();
}
}
return "异步执行结束";
}
@Override
protected void onProgressUpdate(Integer... values) {
pro.setProgress(values[0]);
}
@Override
protected void onPostExecute(String s) {
update.setText(s);
}
}
AsynTask定义了三种泛型类(分别为Params,Progress和Result)和四步骤(onPreExecute,doInBackground,onProcessUpdate和onPostExecute);
三种泛型
Params:启动任务执行的参数,例如请求的url;
Progress:后台任务执行的百分比;
Result:后台执行任务的结果;比如网络请求json等
三种泛型不一定都需要使用,不需要使用的,可以用Void替代;
四步骤:AsynTask执行之后,先后经历四步骤分别为:
1)onPreExecute:在任务开始执行之前,在UIThread调用此方法,可以用来初始化ProgressBar等控件;
2)doInBackground:在onPreExecute执行完成之后,立刻调用后台线程做好事任务,在执行过程中可以调用publicProgress来更新任务的进度;
3)onProcessUpdate:在doInBackground方法中调用publicProgress后,立刻在UIThread中调用,可以更新UI,
4)onPostExecute:在doInBackground方法中后台耗时任务执行结束之后,立刻在UIThread中调用;
Task的执行过程
AsynTask的状态
1)PENDING:未执行
2)RUNNING:执行中
3) FINISHED:已经执行
以Android-23的源码分析;
1)调用execute(),内部调用executeOnExecutor传入sDefaultExecutor线程池
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
executeOnExecutor方法中
@MainThread
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,Params... params) {
//判断在那种状态,一个AsynTask实例只能被执行一次
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();
//execute中的参数传递给mWorker.mParams ;
mWorker.mParams = params;
//把mFuture任务交给线程池sDefaultExecutor
exec.execute(mFuture);
return this;
}
executeOnExecutor方法中先判断AsyncTask实例的状态,当已经执行过之后,再次执行就会抛出异常;只有在PENDING(未执行)状态下,才能够执行,并且把状态更改为RUNNING(运行中)状态,然后执行onPreExecute()方法,可以在此方法中,执行准备工作;把execute(Params... params)方法中的参数传递给mWorker.mParams,sDefaultExecutor线程池执行mFuture任务;
sDefaultExecutor线程池就是SerialExecutor线程池,是一个串行线程池;
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() {//向队列中插入一个runnable
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
//判断是否有runnable在执行,没有就调用scheduleNext方法
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
//从任务队列mTasks中取出任务并放到THREAD_POOL_EXECUTOR线程池中执行. 由此也可见任务是串行进行的。
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
SerialExecutor并不是真正的线程执行者,它只是是保证传递进来的任务Runnable(实例是一个FutureTask)串行执行,确保同时只有一个线程在执行,而真正执行任务的是THREAD_POOL_EXECUTOR线程池,当然该逻辑也体现AsyncTask内部的任务是默认串行进行的,真正执行任务的是THREAD_POOL_EXECUTOR;
THREAD_POOL_EXECUTOR线程池的配置
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();//CPU的核数
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;//核心线程数
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;//最大线程数
private static final int KEEP_ALIVE = 1;//保活时间
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());
}
};
private static final BlockingQueue<Runnable> sPoolWorkQueue =new LinkedBlockingQueue<Runnable>(128); //消息队列最大容量
public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE,KEEP_ALIVE,TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
mWorker和mFuture是什么呢?
mWorker和mFuture都是在AsyncTask的构造函数中初始化
mWorker是WorkerRunnable的实例,在AsyncTask的构造方法中初始化
WorkerRunnable类
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
}
从源码可以看出来,WorkerRunnable是Callable的实现类,内部有一个泛型数组mParams;不了解Callable可阅读线程和线程池的用法先了解下
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);
}
};
WorkerRunnable内部的call()方法中调用doInBackground(mParams);并且返回返回值,call方法return返回值,调用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()方法直接将参数return回去,但是在内部发送Message,InternalHandler处理message消息在InternalHandler的handleMessage中调用finish(Result result)方法,
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
如果没有取消,执行onPostExecute()方法,并且改变AsynTask实例的状态为FINISHED(已完成 ),在onPostExecute()中更新UI,
如果在doInBackground()方法中调用publishProgress()
@WorkerThread
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}
如果Task没有被取消,将发送Message消息,在InternalHandler的handleMessage中调用onProgressUpdate方法,
@SuppressWarnings({"UnusedDeclaration"})
@MainThread
protected void onProgressUpdate(Progress... values) {
}
在onProgressUpdate()中更新进度,
mFuture是FutureTask的实例;再回到executeOnExecutor中,把mFuture任务交给线程池sDefaultExecutor调用exec.execute(mFuture);当WorkerRunnable的call()方法耗时任务执行完成之后,FutureTask 调用done()方法,表示FutureTask执行完成
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);
}
}
};
由于WorkerRunnable的call()有可能返回结果,有可能返回异常,如果返回异常,postResult(result)将不会执行,后续的onPostExecute()也无法执行,就需要在在done()中做异常处理,调用postResultIfNotInvoked();
private void postResultIfNotInvoked(Result result) {
final boolean wasTaskInvoked = mTaskInvoked.get();
if (!wasTaskInvoked) {
postResult(result);
}
}
会看WorkerRunnable的call()方法,先将mTaskInvoked.set(true);如果发生异常,无法设置为true,将为false,调用postResult(result);发送Message消息;在InternalHandler的handleMessage中调用finish(Result result)方法,如果Task没有被取消,执行onPostExecute()方法
以上就是AsyncTask的调用执行逻辑;
AsynTask使用注意事项
1)AsynTask的实例必须在UIThread中调用;
2)execute()必须在UIThread中调用;
3)不能手动调用onPreExecute,doInBackground,onProcessUpdate,onPostExecute方法;
4)一个AsynTask实例只能被执行一次,否则多次调用会抛出异常;
AsynTask最早是执行在一个单一线程中;在Android1.6之后,AsynTask执行在线程池中,允许多个线程同时并发执行;在Android3.1之后,又执行在一个单一线程中,避免并行操作造成常见的应用程序错误;如果需要执行并行操作,调用executeOnExecutor()方法;
以上是AsncTask的基本用法和执行流程的内部源码分析;如有问题,请多指教;