/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
packageandroid.os;
importjava.util.ArrayDeque;
import java.util.concurrent.BlockingQueue;
importjava.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
importjava.util.concurrent.Executor;
import java.util.concurrent.ExecutionException;
importjava.util.concurrent.FutureTask;
import java.util.concurrent.LinkedBlockingQueue;
importjava.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
importjava.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
importjava.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
public abstractclass AsyncTask<Params,Progress,Result>{
privatestatic finalString LOG_TAG= "AsyncTask";
//获取当前的cpu核心数
privatestatic finalint CPU_COUNT= Runtime.getRuntime().availableProcessors();
//线程池核心容量
privatestatic finalint CORE_POOL_SIZE= CPU_COUNT+ 1;
//线程池最大容量
privatestatic finalint MAXIMUM_POOL_SIZE= CPU_COUNT* 2+ 1;
//过剩的空闲线程的存活时间
privatestatic finalint KEEP_ALIVE= 1;
//ThreadFactory 线程工厂,通过工厂方法newThread来获取新线程
privatestatic finalThreadFactory sThreadFactory= newThreadFactory(){
//原子整数,可以在超高并发下正常工作
privatefinal AtomicIntegermCount =new AtomicInteger(1);
publicThread newThread(Runnabler){
returnnew Thread(r,"AsyncTask #" + mCount.getAndIncrement());
}
};
//静态阻塞式队列,用来存放待执行的任务,初始容量:128个
privatestatic finalBlockingQueue<Runnable>sPoolWorkQueue =
newLinkedBlockingQueue<Runnable>(128);
/**
* 静态并发线程池,可以用来并行执行任务,尽管从3.0开始,AsyncTask默认是串行执行任务
* 但是我们仍然能构造出并行的AsyncTask
*/
publicstatic finalExecutor THREAD_POOL_EXECUTOR
=new ThreadPoolExecutor(CORE_POOL_SIZE,MAXIMUM_POOL_SIZE,KEEP_ALIVE,
TimeUnit.SECONDS,sPoolWorkQueue,sThreadFactory);
/**
* 静态串行任务执行器,其内部实现了串行控制,
* 循环的取出一个个任务交给上述的并发线程池去执行
*/
publicstatic finalExecutor SERIAL_EXECUTOR= newSerialExecutor();
//消息类型:发送结果
privatestatic finalint MESSAGE_POST_RESULT= 0x1;
//消息类型:更新进度
privatestatic finalint MESSAGE_POST_PROGRESS= 0x2;
/**静态Handler,用来发送上述两种通知,采用UI线程的Looper来处理消息
* 这就是为什么AsyncTask必须在UI线程调用,因为子线程
* 默认没有Looper无法创建下面的Handler,程序会直接Crash
*/
privatestatic finalInternalHandler sHandler= newInternalHandler();
//默认任务执行器,被赋值为串行任务执行器,就是它,AsyncTask变成串行的了
privatestatic volatileExecutor sDefaultExecutor= SERIAL_EXECUTOR;
//如下两个变量我们先不要深究,不影响我们对整体逻辑的理解
privatefinal WorkerRunnable<Params,Result>mWorker;
privatefinal FutureTask<Result>mFuture;
//任务的状态 默认为挂起,即等待执行,其类型标识为易变的(volatile)
privatevolatile StatusmStatus =Status.PENDING;
//原子布尔型,支持高并发访问,标识任务是否被取消
privatefinal AtomicBooleanmCancelled =new AtomicBoolean();
//原子布尔型,支持高并发访问,标识任务是否被执行过
privatefinal AtomicBooleanmTaskInvoked =new AtomicBoolean();
/*串行执行器的实现,我们要好好看看,它是怎么把并行转为串行的
*目前我们需要知道,asyncTask.execute(Params ...)实际上会调用
*SerialExecutor的execute方法,这一点后面再说明。也就是说:当你的asyncTask执行的时候,
*首先你的task会被加入到任务队列,然后排队,一个个执行
*/
privatestatic classSerialExecutor implements Executor{
//线性双向队列,用来存储所有的AsyncTask任务
finalArrayDeque<Runnable>mTasks =new ArrayDeque<Runnable>();
//当前正在执行的AsyncTask任务
RunnablemActive;
publicsynchronized voidexecute(finalRunnable r){
//将新的AsyncTask任务加入到双向队列中
mTasks.offer(newRunnable(){
publicvoid run(){
try{
//执行AsyncTask任务
r.run();
}finally {
//当前AsyncTask任务执行完毕后,进行下一轮执行,如果还有未执行任务的话
//这一点很明显体现了AsyncTask是串行执行任务的,总是一个任务执行完毕才会执行下一个任务
scheduleNext();
}
}
});
//如果当前没有任务在执行,直接进入执行逻辑
if(mActive== null){
scheduleNext();
}
}
protectedsynchronized voidscheduleNext(){
//从任务队列中取出队列头部的任务,如果有就交给并发线程池去执行
if((mActive= mTasks.poll())!= null){
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
/**
* 任务的三种状态
*/
publicenum Status{
/**
* 任务等待执行
*/
PENDING,
/**
* 任务正在执行
*/
RUNNING,
/**
* 任务已经执行结束
*/
FINISHED,
}
/** 隐藏API:在UI线程中调用,用来初始化Handler */
publicstatic voidinit(){
sHandler.getLooper();
}
/** 隐藏API:为AsyncTask设置默认执行器 */
publicstatic voidsetDefaultExecutor(Executorexec){
sDefaultExecutor= exec;
}
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*/
publicAsyncTask(){
mWorker= newWorkerRunnable<Params,Result>(){
publicResult call()throws Exception{
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
returnpostResult(doInBackground(mParams));
}
};
mFuture= newFutureTask<Result>(mWorker){
@Override
protectedvoid done(){
try{
postResultIfNotInvoked(get());
}catch (InterruptedExceptione){
android.util.Log.w(LOG_TAG,e);
}catch (ExecutionExceptione){
thrownew RuntimeException("An error occured while executing doInBackground()",
e.getCause());
}catch (CancellationExceptione){
postResultIfNotInvoked(null);
}
}
};
}
privatevoid postResultIfNotInvoked(Resultresult){
finalboolean wasTaskInvoked= mTaskInvoked.get();
if(!wasTaskInvoked){
postResult(result);
}
}
//doInBackground执行完毕,发送消息
privateResult postResult(Resultresult){
@SuppressWarnings("unchecked")
Messagemessage =sHandler.obtainMessage(MESSAGE_POST_RESULT,
newAsyncTaskResult<Result>(this,result));
message.sendToTarget();
returnresult;
}
/**
* 返回任务的状态
*/
publicfinal StatusgetStatus(){
returnmStatus;
}
/**
* 这个方法是我们必须要重写的,用来做后台计算
* 所在线程:后台线程
*/
protectedabstract ResultdoInBackground(Params...params);
/**
* 在doInBackground之前调用,用来做初始化工作
* 所在线程:UI线程
*/
protectedvoid onPreExecute(){
}
/**
* 在doInBackground之后调用,用来接受后台计算结果更新UI
* 所在线程:UI线程
*/
protectedvoid onPostExecute(Resultresult){
}
/**
* Runs on the UI thread after {@link #publishProgress} is invoked.
/**
* 在publishProgress之后调用,用来更新计算进度
* 所在线程:UI线程
*/
protectedvoid onProgressUpdate(Progress...values){
}
/**
* cancel被调用并且doInBackground执行结束,会调用onCancelled,表示任务被取消
* 这个时候onPostExecute不会再被调用,二者是互斥的,分别表示任务取消和任务执行完成
* 所在线程:UI线程
*/
@SuppressWarnings({"UnusedParameters"})
protectedvoid onCancelled(Resultresult){
onCancelled();
}
protectedvoid onCancelled(){
}
publicfinal booleanisCancelled(){
returnmCancelled.get();
}
publicfinal booleancancel(booleanmayInterruptIfRunning){
mCancelled.set(true);
returnmFuture.cancel(mayInterruptIfRunning);
}
publicfinal Resultget()throws InterruptedException,ExecutionException {
returnmFuture.get();
}
publicfinal Resultget(longtimeout,TimeUnit unit)throws InterruptedException,
ExecutionException,TimeoutException {
returnmFuture.get(timeout,unit);
}
/**
* 这个方法如何执行和系统版本有关,在AsyncTask的使用规则里已经说明,如果你真的想使用并行AsyncTask,
* 也是可以的,只要稍作修改
* 必须在UI线程调用此方法
*/
publicfinal AsyncTask<Params,Progress,Result>execute(Params...params){
//串行执行
returnexecuteOnExecutor(sDefaultExecutor,params);
//如果我们想并行执行,这样改就行了,当然这个方法我们没法改
//return executeOnExecutor(THREAD_POOL_EXECUTOR, params);
}
/**
* 通过这个方法我们可以自定义AsyncTask的执行方式,串行or并行,甚至可以采用自己的Executor
* 为了实现并行,我们可以在外部这么用AsyncTask:
* asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, Params... params);
* 必须在UI线程调用此方法
*/
publicfinal AsyncTask<Params,Progress,Result>executeOnExecutor(Executorexec,
Params...params){
if(mStatus!= Status.PENDING){
switch(mStatus){
caseRUNNING:
thrownew IllegalStateException("Cannot execute task:"
+" the task is already running.");
caseFINISHED:
thrownew IllegalStateException("Cannot execute task:"
+" the task has already been executed "
+"(a task can be executed only once)");
}
}
mStatus= Status.RUNNING;
//这里#onPreExecute会最先执行
onPreExecute();
mWorker.mParams= params;
//然后后台计算#doInBackground才真正开始
exec.execute(mFuture);
//接着会有#onProgressUpdate被调用,最后是#onPostExecute
returnthis;
}
/**
* 这是AsyncTask提供的一个静态方法,方便我们直接执行一个runnable
*/
publicstatic voidexecute(Runnablerunnable){
sDefaultExecutor.execute(runnable);
}
/**
* 打印后台计算进度,onProgressUpdate会被调用
*/
protectedfinal voidpublishProgress(Progress...values){
if(!isCancelled()){
sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
newAsyncTaskResult<Progress>(this,values)).sendToTarget();
}
}
//任务结束的时候会进行判断,如果任务没有被取消,则onPostExecute会被调用
privatevoid finish(Resultresult){
if(isCancelled()){
onCancelled(result);
}else {
onPostExecute(result);
}
mStatus= Status.FINISHED;
}
//AsyncTask内部Handler,用来发送后台计算进度更新消息和计算完成消息
privatestatic classInternalHandler extends Handler{
@SuppressWarnings({"unchecked","RawUseOfParameterizedType"})
@Override
publicvoid handleMessage(Messagemsg){
AsyncTaskResult result =(AsyncTaskResult)msg.obj;
switch(msg.what){
caseMESSAGE_POST_RESULT:
// There is only one result
result.mTask.finish(result.mData[0]);
break;
caseMESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
privatestatic abstractclass WorkerRunnable<Params,Result>implements Callable<Result>{
Params[]mParams;
}
@SuppressWarnings({"RawUseOfParameterizedType"})
privatestatic classAsyncTaskResult<Data>{
finalAsyncTask mTask;
finalData[]mData;
AsyncTaskResult(AsyncTasktask,Data...data){
mTask= task;
mData= data;
}
}
}