android AsyncTask 源码解读
AsyncTask是对Executor和Handler的组合包装类
AsyncTask是Android提供的轻量级的异步类,它使创建异步任务变得更加简单,不再需要编写任务线程和Handler实例即可完成相同的任务
AsyncTask执行过程:
1、AsyncTask启动、执行过程:execute(Params… params) => executeOnExecutor() => execute(Runnable runnable) => sDefaultExecutor.execute(runnable)
2、任务执行阶段:调用顺序doInBackground()=>publishProgress()=>onProgressUpdate(),阶段性结果
3、执行结束过程调用: 1、cancel() => onCancelled()(需在doInBackground()返回后) UI线程调用。 2、调用isCancelled(),检查执行状态
public abstract class AsyncTask<Params, Progress, Result> {
//Params: 传递给异步任务执行时的参数的类型
//Progress: 执行的进度返回给UI线程的参数的类型
//Result: 异步任务执行完后返回给UI线程的结果的类型
private static final String LOG_TAG = "AsyncTask";
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;
/*
//android
private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;
private static final int KEEP_ALIVE = 1;
*/
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1); // 实例化原子整型类mCount,则mCount的方法是线程安全的
public Thread newThread(Runnable r) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
}
};
private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(128); //链表阻塞队列, 容量大小128
/**
* An {@link Executor} that can be used to execute tasks in parallel.
*/
public static final Executor THREAD_POOL_EXECUTOR // 异步线程池:多任务并发执行线程池
= new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
public static final Executor SERIAL_EXECUTOR = new SerialExecutor(); // 同步线程池(串行线程池): 同一时间只能执行一个任务,串行执行任务,同步方法内调用THREAD_POOL_EXECUTOR.execute()达到最终串行执行任务
private static final int MESSAGE_POST_RESULT = 0x1;
private static final int MESSAGE_POST_PROGRESS = 0x2;
private static final InternalHandler sHandler = new InternalHandler(); // 静态内部类InternalHandler,其绑定了主线程的Looper和消息队列,完成消息的产生、发送、处理,
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; // 默认线程池为串行线程池
private final WorkerRunnable<Params, Result> mWorker;
private final FutureTask<Result> mFuture;
private volatile Status mStatus = Status.PENDING;
private final AtomicBoolean mTaskInvoked = new AtomicBoolean(); //标识当前任务是否调用执行,原子布尔型变量(原子操作就是不能被线程调度机制中断的操作)
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>(); // 数组双端队列,没有容量限制,其容量可自增长, mTasks的集合来保证任务的顺序执行
Runnable mActive;
public synchronized void execute(final Runnable r) { // 同步方法中维护双端队列,同时操作双端队列、调用并发线程池进行任务提交、执行
mTasks.offer(new Runnable() { //通过队列的offer方法将封装了final Runnable r的new Runnable对象添加到队尾
public void run() {
try {
r.run(); //执行r的run方法(最后在在线程池中执行),实现任务功能
} finally {
scheduleNext(); // 同步方法中调用并发线程池提交任务
}
}
});
if (mActive == null) { //当前没有可执行任务,调用scheduleNext方法执行一个Runnable任务
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) { //通过mTasks的poll方法出队操作,删除并返回队头的Runnable,并将返回的Runnable赋值给mActive,
THREAD_POOL_EXECUTOR.execute(mActive); // 调用THREAD_POOL_EXECUTOR的execute方法,提交mActive任务,并在线程池中执行mActive.run()方法
}
}
}
public enum Status {
//Indicates that the task has not been executed yet.
PENDING,
// Indicates that the task is running.
RUNNING,
//Indicates that {@link AsyncTask#onPostExecute} has finished.
FINISHED,
}
//异步任务的当前状态以及状态转变:PENDING=>RUNNING=>FINISHED
public static void init() {
sHandler.getLooper();
}
public static void setDefaultExecutor(Executor exec) {
sDefaultExecutor = exec;
}
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*/
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() { //实现了Callable接口的call方法
public Result call() throws Exception { //call方法是在线程池的线程中执行的,而不是在主线程中运行
mTaskInvoked.set(true); //将mTaskInvoked设置为true,表示任务开始执行
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); // 将当前执行call方法的线程设置为后台线程
Result result = doInBackground(mParams); //在线程池的工作线程中执行doInBackground方法,执行实际的任务,并返回结果
Binder.flushPendingCommands();
return postResult(result); //将执行完的结果传递给postResult方法
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
try {
final Result result = get();
postResultIfNotInvoked(result); // 任务正常执行完成
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occured while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null); // 任务取消
} catch (Throwable t) {
throw new RuntimeException("An error occured while executing "
+ "doInBackground()", t);
}
}
};
}
private void postResultIfNotInvoked(Result result) {
final boolean wasTaskInvoked = mTaskInvoked.get();
if (!wasTaskInvoked) {
postResult(result);
}
}
private Result postResult(Result result) {
Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result)); // 发送“结果消息”
message.sendToTarget();
return result;
}
public final Status getStatus() {
return mStatus;
}
/**
* Override this method to perform a computation on a background thread. The
* specified parameters are the parameters passed to {@link #execute}
* by the caller of this task.
*
* This method can call {@link #publishProgress} to publish updates on the UI thread.
*
* @param params The parameters of the task.
*
* @return A result, defined by the subclass of this task.
*/
protected abstract Result doInBackground(Params... params);
/**
* Runs on the UI thread before doInBackground()
*/
protected void onPreExecute() {
}
/**
* Runs on the UI thread after doInBackground(). This method won't be invoked if the task was cancelled
* @param result: The result of the operation computed by #doInBackground
*/
@SuppressWarnings({"UnusedDeclaration"})
protected void onPostExecute(Result result) {
}
/**
* Runs on the UI thread after publishProgress() is invoked.
* @param values The values indicating progress.
*/
@SuppressWarnings({"UnusedDeclaration"})
protected void onProgressUpdate(Progress... values) {
}
@SuppressWarnings({"UnusedParameters"})
protected void onCancelled(Result result) {
onCancelled();
}
protected void onCancelled() {
}
/**
* Returns <tt>true</tt> if this task was cancelled before it completed
* normally. If you are calling {@link #cancel(boolean)} on the task,
* the value returned by this method should be checked periodically from
* {@link #doInBackground(Object[])} to end the task as soon as possible.
*
* @return <tt>true</tt> if task was cancelled before it completed
*/
public final boolean isCancelled() {
return mFuture.isCancelled();
}
/**
* <p>Attempts to cancel execution of this task. This attempt will
* fail if the task has already completed, already been cancelled,
* or could not be cancelled for some other reason. If successful,
* and this task has not started when <tt>cancel</tt> is called,
* this task should never run. If the task has already started,
* then the <tt>mayInterruptIfRunning</tt> parameter determines
* whether the thread executing this task should be interrupted in
* an attempt to stop the task.</p>
*
* @param mayInterruptIfRunning
* true:if the thread executing this task should be interrupted; otherwise, in-progress tasks are allowed to complete.
* @return false: if the task could not be cancelled, typically because it has already completed normally; true:otherwise
*
* @see #isCancelled()
* @see #onCancelled(Object)
*/
// 取消当前执行任务
public final boolean cancel(boolean mayInterruptIfRunning) { //3、执行结束过程调用: cancel() => doInBackground()返回 => onCancelled() UI线程调用。 2、调用isCancelled(),检查执行状态
return mFuture.cancel(mayInterruptIfRunning);
}
public final Result get() throws InterruptedException, ExecutionException {
return mFuture.get();
}
/**
* Waits if necessary for at most the given time for the computation to complete, and then retrieves its result.
* @param timeout Time to wait before cancelling the operation.
* @param unit The time unit for the timeout.
* @return The computed result.
*/
//等待计算完成,获取任务状态结果
public final Result get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return mFuture.get(timeout, unit);
}
/**
* Executes the task with the specified parameters. The task returns
* itself (this) so that the caller can keep a reference to it.
* This method must be invoked on the UI thread.
* @param params The parameters of the task.
* @return This instance of AsyncTask.
*/
//传入参数,开始执行任务
public final AsyncTask<Params, Progress, Result> execute(Params... params) { // 1、AsyncTask启动、执行过程:execute(Params... params) => executeOnExecutor() => execute(Runnable runnable) => sDefaultExecutor.execute(runnable)
return executeOnExecutor(sDefaultExecutor, params);
}
/**
* Executes the task with the specified parameters. The task returns
* itself (this) so that the caller can keep a reference to it.
* This method must be invoked on the UI thread.
*
* @param exec The executor to use. #THREAD_POOL_EXECUTOR} is available as a convenient process-wide thread pool for tasks that are loosely coupled.
* @param params The parameters of the task.
*
* @return This instance of AsyncTask.
*/
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();
mWorker.mParams = params;
exec.execute(mFuture);
return this;
}
public static void execute(Runnable runnable) {
sDefaultExecutor.execute(runnable); //由默认线程池提交、执行任务
}
protected final void publishProgress(Progress... values) { // 2、任务执行阶段:调用顺序doInBackground()=>publishProgress()=>onProgressUpdate(),阶段性结果
if (!isCancelled()) {
sHandler.obtainMessage(MESSAGE_POST_PROGRESS, new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result); // 任务被取消,执行onCancelled()方法
} else {
onPostExecute(result); //结果发传递给onPostExecute()方法, 可在UI线程中刷新结果
}
mStatus = Status.FINISHED; //AsyncTask的状态设置为完成状态
}
private static class InternalHandler extends Handler {
public InternalHandler() {
super(Looper.getMainLooper()); //Looper类的getMainLooper静态方法,该方法返回主线程的Looper,表示InternalHandler绑定了主线程
}
@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
result.mTask.finish(result.mData[0]); //任务完成后调用:更新状态,显示结果等
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData); // 可在UI线程中刷新显示执行进度
break;
}
}
}
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
}
@SuppressWarnings({"RawUseOfParameterizedType"})
private static class AsyncTaskResult<Data> { // 封装AsyncTask与相关数据成AsyncTaskResult
final AsyncTask mTask;
final Data[] mData; //存储的数据
AsyncTaskResult(AsyncTask task, Data... data) { //data是可变数组
mTask = task;
mData = data;
}
}
}
AsyncTask使用关键函数:
protected void onPreExecute(); // 当任务执行之前开始调用此方法,可以在这里显示进度对话框,属UI主线程。
protected abstract Result doInBackground(Params… params);//耗时操作,例如网络请求任务。由AsyncTask线程池中的线程调用执行异步任务
protected void onPostExecute(Result result);//处理doInBackground得到的数据,能够对UI进行操作,属UI主线程
protected void onProgressUpdate(Progress… values); //可以使用进度条增加用户体验度。 属UI主线程,用于显示任务执行的进度。
protected void onCancelled(Result result); //用户调用取消时,会调用此方法,属UI主线程
使用AsyncTask类,须遵守的准则:
Task的实例必须在UI thread中创建;
execute方法必须在UI thread中调用;
不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params…), onProgressUpdate(Progress…)这几个方法;
该task只能被执行一次,多次调用时将会出现异常;
示例:
public class MainActivity extends Activity
{
private Button button;
private Button cancel;
private ImageView imageView;
private ProgressDialog progressDialog;
private final String IMAGE_PATH = "http://developer.android.com/images/home/kk-hero.jpg";
DownloadAsyncTask task;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView)findViewById(R.id.imageView);
progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setTitle("Image Downloading");
progressDialog.setMessage("........Downloading......");
progressDialog.setCancelable(false);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
button = (Button)findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v){
task = new DownloadAsyncTask();
task.execute(IMAGE_PATH); //AsyncTask任务只能被执行一次,传入参数,开始执行异步任务
//函数原型:public final AsyncTask<Params, Progress, Result> execute(Params... params)
cancel.setEnabled(true);
}
});
cancel = (Button) findViewById(R.id.cancel);
cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
task.cancel(true); //取消一个正在执行的任务
}
});
cancel.setEnabled(false);
}
public class DownloadAsyncTask extends AsyncTask<String, Integer, byte[]> //Params: String类型,指定的URL路径,进度参数Progress: Integer类型,返回值类型Result:byte[]类型
{
@Override
protected void onPreExecute(){ // UI 线程执行
super.onPreExecute();
progressDialog.show(); //ProgressDialog显示出来
}
@Override
protected byte[] doInBackground(String... params) // 异步线程(后台线程)中执行
{
ByteArrayOutputStream bos=new ByteArrayOutputStream();
byte[] imgBytes = new byte[]{};
try {
URL url=new URL(params[0]);
HttpURLConnection con=(HttpURLConnection)url.openConnection();
con.setConnectTimeout(5000);
con.setReadTimeout(5000);
con.setDoInput(true);
con.connect();
InputStream is=con.getInputStream();
long maxSize=con.getContentLength(); //获取文件的大小
byte[] buffer=new byte[1024];
int len=-1;
long total_length=0;
while((len=is.read(buffer))!=-1){
bos.write(buffer,0,len);
bos.flush();
total_length += len;
int progress = ((int)(total_length/(float)maxSize) * 100); // 得到当前图片下载的进度
publishProgress(progress); //将当前进度更新给onProgressUpdate方法
}
is.close(); //关闭输入流
con.disconnect(); //关闭连接
byte[] imgBytes=bos.toByteArray();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return imgBytes;
}
@Override
protected void onProgressUpdate(Integer... values){ // UI 线程执行
super.onProgressUpdate(values);
progressDialog.setProgress(values[0]); //更新ProgressDialog的进度条
}
@Override
protected void onPostExecute(byte[] result){ // UI 线程执行
super.onPostExecute(result);
Bitmap bitmap = BitmapFactory.decodeByteArray(result, 0, result.length);
imageView.setImageBitmap(bitmap);
progressDialog.dismiss();
}
@Override
protected void onCancelled() { //取消执行中的任务时更改UI
progressDialog.setProgress(0);
cancel.setEnabled(false);
}
}
}