AsyncTask.java
AsycnTask-Api
AsyncTask是后台执行操作在UI线程发布结果的对象,很轻松的使用UI线程,用于耗时较短的后台操作。
AsyncTask原理
AsyncTas类初始化sDefaultExecutor和sHandler变量,用于执行后台执行任务和分发消息给主线程
AsyncTask对象创建时实现后台执行函数doInBackground()和发布UI结果的回调函数onPostExecute()
构造AsyncTask时
构建类型为WorkerRunnable的mWork对象,执行doInBackground(),然后发送结束消息给sHandler
构建类型FutureTask的mFuture对象,以mWork为回调参数,并重写任务结束回调方法done(),如果上面没有发送消息没有成功会再次发给sHandler
mWork和mFuture中发送消息都调用postResult(),message的obj指向的是AsyncTaskResult对象,其包含AsyncTask对象和消息类型标记
execute()启动时在执行线程池处理任务之前先调用onPreExecute()
mFuture进入sDefaultExecutor线程池任务队列消费
任务执行结束调用FutureTask的done()方法,将执行完毕消息通过postResult()发送给sHandler
sHandler收到消息根据what标记分别调用asyncTask对象的发布结果回调方法和更新UI进度方法
注明:
AsyncTask必须在主线程中创建
后台执行回调调用publishProgress()就是发送更新进度消息给sHandler
动手实现
public abstract class AsyncTask<Params, Progress, Result> {
private static final int MESSAGE_POST_RESULT = 1;//结束标记
private static final int MESSAGE_POST_PROGRESS = 2;//更新进度标记
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();//cpu核心数
//最少2个或者4个核心线程
//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;
private static final int KEEP_ALIVE_SECONDS = 30;
//线程创建工厂
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
////参数2为线程名字
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
}
};
//最多容纳128个任务,再多任务就会被阻塞
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);
static {
//初始化线程执行器配置
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
sDefaultExecutor = threadPoolExecutor;//暂不使用哪个串行执行的执行器
}
private static volatile Executor sDefaultExecutor;
private static InternalHandler sHnadler;
//不适用懒加载直接使用
static {
sHnadler = new InternalHandler();
}
private final WorkerRunnable<Params, Result> mWorker;
private final FutureTask<Result> mFuture;
public AsyncTask() {
//mWorker的参数在execute的时候补上
mWorker = new WorkerRunnable<Params, Result>() {
@Override
public Result call() throws Exception {
Result result = doInBackground(mParams);//调用后台执行操作
postResult(result);//通知handler调用发布结果回调
return result;
}
};
mFuture = new FutureTask<Result>(mWorker);//暂不包装二次检查发送
}
//发送结束消息给handler
private void postResult(Result result) {
Message message = Message.obtain();
message.what = MESSAGE_POST_RESULT;
message.obj = new AsyncTaskResult(this, result);
}
//发送更新消息给handler
protected void publishProgress(Progress... values) {
Message message = Message.obtain();
message.what = MESSAGE_POST_PROGRESS;
message.obj = new AsyncTaskResult(this, values);
}
//执行任务
public void execute(Params... values) {
onPreExecute();
mWorker.mParams = values;
sDefaultExecutor.execute(mFuture);
}
protected void onPreExecute() {
}
//后台操作回调
protected abstract Result doInBackground(Params... var1);
//发布结果回调
protected void onPostExecute(Result result) {
}
//进度回调
protected void onProgressUpdate(Progress... values) {
}
//主线程处理消息调用asyncTask的回调
private static class InternalHandler extends Handler {
public InternalHandler() {
super(Looper.getMainLooper());
}
@Override
public void handleMessage(Message msg) {
AsyncTaskResult result = (AsyncTaskResult) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
result.mTask.onPostExecute(result.mData[0]);//发布结果回调
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);//更新进度回调
break;
}
}
}
//通过线程传递给doInBackground用户定义好的参数
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
}
//消息携带类
private static class AsyncTaskResult<Result> {
AsyncTask mTask;//消息发送所属AsyncTask
Result[] mData;//结果参数
public AsyncTaskResult(AsyncTask mTask, Result... mData) {
this.mTask = mTask;
this.mData = mData;
}
}
}
使用
asyncTask.execute("http://www.baidu.com");
...
AsyncTask<String, Long, String> asyncTask = new AsyncTask<String, Long, String>() {
@Override
protected String doInBackground(String... strings) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello";
}
@Override
protected void onPostExecute(String value) {
super.onPostExecute(value);
Toast.makeText(MainActivity.this, value + " over", Toast.LENGTH_SHORT).show();
}
};