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();
}
};
複製程式碼