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>() {@Overridepublic Result call() throws Exception {Result result = doInBackground(mParams);//调用后台执行操作postResult(result);//通知handler调用发布结果回调return result;}};mFuture = new FutureTask<Result>(mWorker);//暂不包装二次检查发送}//发送结束消息给handlerprivate void postResult(Result result) {Message message = Message.obtain();message.what = MESSAGE_POST_RESULT;message.obj = new AsyncTaskResult(this, result);}//发送更新消息给handlerprotected 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());}@Overridepublic 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;//消息发送所属AsyncTaskResult[] 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>() {@Overrideprotected String doInBackground(String... strings) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}return "hello";}@Overrideprotected void onPostExecute(String value) {super.onPostExecute(value);Toast.makeText(MainActivity.this, value + " over", Toast.LENGTH_SHORT).show();}};
复制代码