AsyncTask大家都不會陌生吧,當然現(xiàn)在有比如RxJava這種替代方案觉壶,但是AsyncTask我們還是要去分析的夏伊,這樣我們能更好的理解Android系統(tǒng)是怎樣運行的刑峡。AsyncTask內部封裝了Thread和Handler纵菌,簡化了他們的使用阐污,我們都知道子線程中是不能更新UI的,我們需要在子線程中計算然后在主線程中更新UI咱圆,AsyncTask就提供了這么一種簡便的實現(xiàn)方式笛辟。
簡要說明AsyncTask的重要的一些函數(shù)
- AsyncTask<Params,Progress,Result>定義的三種泛型類型
Params:啟動任務執(zhí)行的輸入?yún)?shù),比如一下下載任務的Url序苏。
Progress:異步任務的執(zhí)行的百分比手幢。
Result:后臺任務執(zhí)行完成返回的結果,比如下載完成返回文件的path路徑忱详。- doInBackground():運行在后臺線程围来,做耗時操作,可以通過 publishProgress()方法更新進度,子線程监透。
- onPostExecute():獲取到doInBackground()中的result然后做出處理钦铁,比如更新UI,主線程才漆。
- onProgressUpdate(Progress…):更新任務進度;
- onPreExecute():在調用Excute之前調用佛点,可以顯示進度對話框醇滥;
- onCancelled():用戶調用取消時要做的操作。
一個簡單的示例超营,部分偽代碼
public class ProgressAsyncTask extends AsyncTask<String,Integer,String> {
@Override
protected String doInBackground(String... params) {
//url代表下載地址
String url = params[0];
long totalSize = 0;
long currentSize = 0;
String filePath="";
//... URLConnection做下載操作
totalSize = 1228339;
//更新 currentSize
publishProgress(((int) (currentSize / totalSize*100)));
return filePath;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
//progressDialog.setProgress(values[0]);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
//showProgressDialog();
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
//showDialog("下載完成鸳玩,下載地址:"+s);
}
}
AsyncTask源碼分析
public abstract class AsyncTask<Params, Progress, Result> {
private static final String LOG_TAG = "AsyncTask”;
//cpu核心數(shù)
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
//核心線程數(shù)的區(qū)間是[2,4]
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;
//當一個線程空閑30秒后就會被取消
private static final int KEEP_ALIVE_SECONDS = 30;
//線程工廠 通過工廠方法newThread來創(chuàng)建新的線程
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
//原子整數(shù) 可以在高并發(fā)下正常工作
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
}
};
//靜態(tài)阻塞式隊列,用來存放待執(zhí)行的任務演闭,初始容量:128個
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);
//靜態(tài)并發(fā)線程池不跟,可以用來并行執(zhí)行任務,3.0開始米碰,AsyncTask默認是串行執(zhí)行任務窝革,我們可以構造并行的AsyncTask
public static final Executor THREAD_POOL_EXECUTOR;
static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}
//靜態(tài)串行的任務執(zhí)行器,內部實現(xiàn)了線程控制吕座,循環(huán)的一個個取出任務交給并發(fā)線程池去執(zhí)行
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
//消息類型 結果
private static final int MESSAGE_POST_RESULT = 0x1;
//消息類型 進度
private static final int MESSAGE_POST_PROGRESS = 0x2;
//默認的任務執(zhí)行器虐译,這里使用的是串行的任務執(zhí)行器,所以AsyncTask是串行的
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
//靜態(tài)的Handler吴趴,AsyncTask必須在UI線程中執(zhí)行是因為Handler用的是UI線程的Looper漆诽,子線程沒有Looper
private static InternalHandler sHandler;
private final WorkerRunnable<Params, Result> mWorker;
private final FutureTask<Result> mFuture;
//任務狀態(tài) 默認為掛起 標識為易變的volatile
private volatile Status mStatus = Status.PENDING;
//原子布爾型 高并發(fā)支持 任務是否被取消
private final AtomicBoolean mCancelled = new AtomicBoolean();
//任務是否貝執(zhí)行過
private final AtomicBoolean mTaskInvoked = new AtomicBoolean();
//串行的任務執(zhí)行器,當asyncstask執(zhí)行的時候會加入到任務隊列中一個個執(zhí)行
private static class SerialExecutor implements Executor {
//線性的雙向隊列 用來存儲所有的AsyncTask任務
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
//當前正在執(zhí)行的任務
Runnable mActive;
//將新的任務加入到雙向隊列中
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
//執(zhí)行任務
r.run();
} finally {
//如果還有任務锣枝,則上一個任務執(zhí)行完畢后執(zhí)行下一個任務
scheduleNext();
}
}
});
//當前任務為空 則進入下一個任務
if (mActive == null) {
scheduleNext();
}
}
//從任務棧的頭部取出任務厢拭,交給并發(fā)線程池執(zhí)行任務
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
//任務的狀態(tài) 等待執(zhí)行,正在執(zhí)行撇叁,執(zhí)行完成
public enum Status {
PENDING,
RUNNING,
FINISHED,
}
//同步鎖 初始化Handler
private static Handler getHandler() {
synchronized (AsyncTask.class) {
if (sHandler == null) {
sHandler = new InternalHandler();
}
return sHandler;
}
}
/** @hide */
//隱藏的類 設置默認線程執(zhí)行器
public static void setDefaultExecutor(Executor exec) {
sDefaultExecutor = exec;
}
//AsyncTask的構造函數(shù)
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
//...
//result = doInBackground(mParams);
//...
return result;
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
//...
}
};
}
private void postResultIfNotInvoked(Result result) {
final boolean wasTaskInvoked = mTaskInvoked.get();
if (!wasTaskInvoked) {
postResult(result);
}
}
//執(zhí)行完畢發(fā)送消息
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
//返回當前任務狀態(tài)
public final Status getStatus() {
return mStatus;
}
//抽象類 在子線程中執(zhí)行
@WorkerThread
protected abstract Result doInBackground(Params... params);
//在Execute之前執(zhí)行
@MainThread
protected void onPreExecute() {
}
//任務完畢 返回結果
@MainThread
protected void onPostExecute(Result result) {
}
//更新任務進度
@MainThread
protected void onProgressUpdate(Progress... values) {
}
//Cancel被調用并且doInBackground執(zhí)行完畢供鸠,onCancelled被調用,表示任務取消陨闹,onPostExecute不會被調用
@MainThread
protected void onCancelled(Result result) {
onCancelled();
}
@MainThread
protected void onCancelled() {
}
public final boolean isCancelled() {
return mCancelled.get();
}
//取消正在執(zhí)行的任務
public final boolean cancel(boolean mayInterruptIfRunning) {
mCancelled.set(true);
return mFuture.cancel(mayInterruptIfRunning);
}
public final Result get() throws InterruptedException, ExecutionException {
return mFuture.get();
}
//sDefaultExecutor默認串行執(zhí)行器 如果我們要改成并發(fā)的執(zhí)行方式直接使用executeOnExecutor這個方法
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
//可以指定執(zhí)行器
@MainThread
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;
}
//更新任務進度 onProgressUpdate會被調用
@WorkerThread
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}
//任務執(zhí)行完畢 如果沒有被取消執(zhí)行onPostExecute()方法
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
//AsyncTask內部Handler
private static class InternalHandler extends Handler {
public InternalHandler() {
super(Looper.getMainLooper());
}
@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);
break;
}
}
}
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
}
@SuppressWarnings({"RawUseOfParameterizedType"})
private static class AsyncTaskResult<Data> {
final AsyncTask mTask;
final Data[] mData;
AsyncTaskResult(AsyncTask task, Data... data) {
mTask = task;
mData = data;
}
}
}
好了回季,源碼我們分析完畢,請仔細看注釋和重要函數(shù)的執(zhí)行位置正林。其實梳理了下AsyncTask源碼我們發(fā)現(xiàn)泡一,它其實是內部封裝了Thead和Handler,這樣對外暴露一些必要的方法觅廓,符合我們六大設計原則中的迪米特原則鼻忠,也就是最少知識原則,我們在使用的過程中不必關心它的內部實現(xiàn),只需要在doInBackground()中做計算操作帖蔓,onProgressUpdate()中更新UI就可以了矮瘟。
AsyncTask的一些問題
- API 16 以前必須在主線程加載 AsyncTask,API 16 以后就不用了;
- 因為每個AsyncTask只能執(zhí)行一次塑娇,多次調用同一個AsyncTask對象會出現(xiàn)異常澈侠。但如果要處理多個后臺任務,你需要創(chuàng)建多個AsyncTask并執(zhí)行execute()埋酬;
- API 4-11 默認是AsnckTask任務并發(fā)執(zhí)行哨啃,API11后默認是順序執(zhí)行,任務是順序執(zhí)行写妥,必須等一個任務結束才能執(zhí)行下一個拳球。但是可以通過executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)來進行并行執(zhí)行任務,在并行執(zhí)行任務時珍特,有最大執(zhí)行個數(shù)的限制
- AsyncTask需要在UI線程調用execute()函數(shù)祝峻,因為onPreExecute()在UI線程執(zhí)行
參考
任玉剛《Android開發(fā)藝術探索》
基于最新版本的AsyncTask源碼解讀及AsyncTask的黑暗面