package android.os;
import android.annotation.MainThread;
import android.annotation.Nullable;
import android.annotation.WorkerThread;
import java.util.ArrayDeque;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.FutureTask;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
/**
* ä½è
ï¼å¶åºæ¯å¶
* æ¶é´ï¼2018/6/24 15:01
* æè¿°ï¼https://github.com/leavesC/Java_Android_Learn
* https://www.jianshu.com/u/9df45b87cfdf
*/
public abstract class AsyncTask {
private static final String LOG_TAG = "AsyncTask";
//CPU æ ¸æ°é
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
//çº¿ç¨æ± ä¸çæ ¸å¿çº¿ç¨æ°
//è³å°æ2ä¸ªï¼æå¤4个ï¼çº¿ç¨æ°è³å°è¦æ¯ CPU æ ¸æ°éå°1个ï¼ä»¥é¿å
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;
//线ç¨å¨é²ç½®æ¶çåæ´»æ¶é´ï¼30ç§ï¼ï¼è¶
åºè¿ä¸ªæ¶é´å°è¢«åæ¶
private static final int KEEP_ALIVE_SECONDS = 30;
//线ç¨éå
//å½ LinkedBlockingDeque 已满æ¶ï¼æ°å¢çä»»å¡ä¼ç´æ¥å建æ°çº¿ç¨æ¥æ§è¡ï¼å½å建ççº¿ç¨æ°éè¶
è¿æå¤§çº¿ç¨æ°é KEEP_ALIVE_SECONDS æ¶ä¼æåºå¼å¸¸
private static final BlockingQueue sPoolWorkQueue = new LinkedBlockingQueue(128);
//线ç¨å·¥åï¼æä¾å建æ°çº¿ç¨çåè½ï¼éè¿çº¿ç¨å·¥åå¯ä»¥å¯¹çº¿ç¨çä¸äºå±æ§è¿è¡å®å¶
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
}
};
//çº¿ç¨æ± 对象
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);
//å
æ¬æ ¸å¿çº¿ç¨å¨å
çææçº¿ç¨å¨é²ç½®æ¶é´è¶
åº KEEP_ALIVE_SECONDS åé½å°å
¶åæ¶
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}
//串è¡ä»»å¡æ§è¡å¨ï¼å³æäº¤ç»çº¿ç¨æ± ç任塿¯æç
§é¡ºåºï¼çä¸ä¸ä¸ªæ§è¡ç»æåæ§è¡ä¸ä¸ä¸ªç
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
//ç¨äºå½ä»»å¡å®ææ¶ä¼ éæ§è¡ç»æ
private static final int MESSAGE_POST_RESULT = 0x1;
//ç¨äºæ´æ°ä»»å¡çè¿åº¦å¼
private static final int MESSAGE_POST_PROGRESS = 0x2;
//å½å Task 使ç¨ç任塿§è¡å¨
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
//æç
§æ£å¸¸æ
嵿¥è¯´ï¼å¨åå§å AsyncTask æ¶æä»¬ä½¿ç¨ç齿¯å
¶æ åæé 彿°
//å æ¤ InternalHandler ç»å®ç Looper å¯¹è±¡å³æ¯ä¸ä¸»çº¿ç¨å
³èç Looper 对象
//æä»¥ InternalHandler å¯ä»¥ç¨æ¥å¨ UI 线ç¨åè°æäºæ½è±¡æ¹æ³ï¼ä¾å¦ onProgressUpdate() æ¹æ³
private static InternalHandler sHandler;
//çäº sHandler
private final Handler mHandler;
private final WorkerRunnable mWorker;
private final FutureTask mFuture;
//å½å Task çç¶æ
private volatile Status mStatus = Status.PENDING;
//ç¨äºæ è®°å½ååå°ä»»å¡æ¯å¦å·²è¢«åæ¶
private final AtomicBoolean mCancelled = new AtomicBoolean();
//ç¨äºæ è®°å½ååå°ä»»å¡æ¯å¦å·²è¢«æ§è¡
private final AtomicBoolean mTaskInvoked = new AtomicBoolean();
//串è¡ä»»å¡æ§è¡å¨ï¼å³æäº¤ç»çº¿ç¨æ± ç任塿¯æç
§é¡ºåºä¸ä¸ªæ¥ä¸ä¸ªè¢«æ§è¡ç
private static class SerialExecutor implements Executor {
//ä»»å¡éå
final ArrayDeque mTasks = new ArrayDeque();
//å½å卿§è¡çä»»å¡
Runnable mActive;
public synchronized void execute(final Runnable r) {
//åä»»å¡éå尾端æå
¥ä»»å¡
//å¨å¤é¨ä»»å¡å¤é¨å
è£
å¤ä¸å± Runnable
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
//妿å½å没æå¨æ§è¡ä»»å¡ï¼åè°åéåä¸çä»»å¡è¿è¡å¤ç
if (mActive == null) {
scheduleNext();
}
}
//è·åéåçé¦ä¸ªä»»å¡å¹¶å¤ç
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
private static class InternalHandler extends Handler {
public InternalHandler(Looper looper) {
super(looper);
}
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
public void handleMessage(Message msg) {
AsyncTaskResult> result = (AsyncTaskResult>) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
//å¤çåå°ä»»å¡çæ§è¡ç»æ
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
//æ´æ°åå°ä»»å¡çè¿åº¦
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
private static abstract class WorkerRunnable implements Callable {
Params[] mParams;
}
@SuppressWarnings({"RawUseOfParameterizedType"})
private static class AsyncTaskResult {
final AsyncTask mTask;
final Data[] mData;
AsyncTaskResult(AsyncTask task, Data... data) {
mTask = task;
mData = data;
}
}
//ç¨äºæ è®° Task çå½åç¶æ
public enum Status {
//Task è¿æªè¿è¡
PENDING,
//Task æ£å¨è¿è¡
RUNNING,
//Task å·²ç»ç»æ
FINISHED,
}
//è·åä¸ä¸»çº¿ç¨å
³èç Looper 对象ï¼ä»¥æ¤ä¸ºåæ°æå»ºä¸ä¸ª Handler 对象
//æä»¥å¨ Task çè¿è¡è¿ç¨ä¸ï¼è½å¤éè¿æ¤ Handler å¨ UI çº¿ç¨æ§è¡æä½
private static Handler getMainHandler() {
synchronized (AsyncTask.class) {
if (sHandler == null) {
sHandler = new InternalHandler(Looper.getMainLooper());
}
return sHandler;
}
}
private Handler getHandler() {
return mHandler;
}
//éè彿°
public static void setDefaultExecutor(Executor exec) {
sDefaultExecutor = exec;
}
//å建ä¸ä¸ªæ°ç弿¥ä»»å¡ï¼å¿
é¡»å¨UI线ç¨ä¸è°ç¨æ¤æé 彿°
public AsyncTask() {
this((Looper) null);
}
/**
* éèçæé 彿°
* å建ä¸ä¸ªæ°ç弿¥ä»»å¡ï¼å¿
é¡»å¨UI线ç¨ä¸è°ç¨æ¤æé 彿°
*
* @hide
*/
public AsyncTask(@Nullable Handler handler) {
this(handler != null ? handler.getLooper() : null);
}
/**
* éèçæé 彿°
* å建ä¸ä¸ªæ°ç弿¥ä»»å¡ï¼å¿
é¡»å¨UI线ç¨ä¸è°ç¨æ¤æé 彿°
* @hide
*/
public AsyncTask(@Nullable Looper callbackLooper) {
//妿 callbackLooper 为 null æè
æ¯çäºä¸»çº¿ç¨ Looper ï¼åä»¥ä¸»çº¿ç¨ Looper å¯¹è±¡ä¸ºåæ°æå»ºä¸ä¸ªä¸ä¸»çº¿ç¨å
³èç Handler 对象
//å¦åå°±ä»¥ä¼ å
¥ç Looper å¯¹è±¡ä¸ºåæ°æ¥æå»ºä¸å线ç¨å
³èç Handler
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper() ? getMainHandler() : new Handler(callbackLooper);
mWorker = new WorkerRunnable() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Result result = null;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
postResult(result);
}
return result;
}
};
mFuture = new FutureTask(mWorker) {
@Override
protected void done() {
try {
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occurred while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
}
private void postResultIfNotInvoked(Result result) {
final boolean wasTaskInvoked = mTaskInvoked.get();
if (!wasTaskInvoked) {
postResult(result);
}
}
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult(this, result));
message.sendToTarget();
return result;
}
//è·åå½å Task çç¶æ
public final Status getStatus() {
return mStatus;
}
//å¨å线ç¨ä¸è¢«è°ç¨ï¼ç¨äºæ§è¡åå°ä»»å¡
@WorkerThread
protected abstract Result doInBackground(Params... params);
//å¨ UI 线ç¨ä¸è¢«è°ç¨ï¼å¨ doInBackground() æ¹æ³ä¹åè°ç¨ï¼ç¨äºå¨åå°ä»»å¡å¼å§ååä¸äºåå¤å·¥ä½
@MainThread
protected void onPreExecute() {
}
//å¨ UI 线ç¨ä¸è¢«è°ç¨ï¼å¨ doInBackground() æ¹æ³ä¹åè°ç¨ï¼ç¨äºå¤çåå°ä»»å¡çæ§è¡ç»æ
//åæ° result æ¯ doInBackground() æ¹æ³çè¿åå¼
@SuppressWarnings({"UnusedDeclaration"})
@MainThread
protected void onPostExecute(Result result) {
}
//å¨ UI 线ç¨ä¸è¢«è°ç¨ï¼å½è°ç¨äº publishProgress() æ¹æ³å被触å
//ç¨äºæ´æ°ä»»å¡è¿åº¦å¼
@SuppressWarnings({"UnusedDeclaration"})
@MainThread
protected void onProgressUpdate(Progress... values) {
}
//å¨ UI 线ç¨ä¸è¢«è°ç¨
//å½è°ç¨äº cancel(boolean) æ¹æ³åæ¶åå°ä»»å¡åä¼è¢«è°ç¨
//å¨ doInBackground() æ¹æ³ç»ææ¶ä¹ä¼è¢«è°ç¨
//æ¹æ³å
é¨é»è®¤è°ç¨äº onCancelled() æ¹æ³
@SuppressWarnings({"UnusedParameters"})
@MainThread
protected void onCancelled(Result result) {
onCancelled();
}
//å¨ UI 线ç¨ä¸è¢«è°ç¨ï¼è¢« onCancelled(Result) æ¹æ³è°ç¨
@MainThread
protected void onCancelled() {
}
//妿 Task å¨å®æä¹åè¢«åæ¶äºåè¿å true
public final boolean isCancelled() {
return mCancelled.get();
}
//åæ¶ä»»å¡
public final boolean cancel(boolean mayInterruptIfRunning) {
mCancelled.set(true);
return mFuture.cancel(mayInterruptIfRunning);
}
/**
* Waits if necessary for the computation to complete, and then
* retrieves its result.
*
* @return The computed result.
* @throws CancellationException If the computation was cancelled.
* @throws ExecutionException If the computation threw an exception.
* @throws InterruptedException If the current thread was interrupted
* while waiting.
*/
public final Result get() throws InterruptedException, ExecutionException {
return mFuture.get();
}
/**
* Waits if necessary for at most the given time for the computation
* to complete, and then retrieves its result.
*
* @param timeout Time to wait before cancelling the operation.
* @param unit The time unit for the timeout.
* @return The computed result.
* @throws CancellationException If the computation was cancelled.
* @throws ExecutionException If the computation threw an exception.
* @throws InterruptedException If the current thread was interrupted
* while waiting.
* @throws TimeoutException If the wait timed out.
*/
public final Result get(long timeout, TimeUnit unit) throws InterruptedException,
ExecutionException, TimeoutException {
return mFuture.get(timeout, unit);
}
//以é»è®¤ç串è¡ä»»å¡æ§è¡å¨ sDefaultExecutor æ¥æ§è¡åå°ä»»å¡
@MainThread
public final AsyncTask execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
//以æå®ç任塿§è¡å¨ Executor æ¥æ§è¡åå°ä»»å¡
@MainThread
public final AsyncTask executeOnExecutor(Executor exec, Params... params) {
//Task åªè½è¢«æ§è¡ä¸æ¬¡ï¼å¦æ mStatus != Status.PENDING ï¼è¯´æ Task 被é夿§è¡ï¼æ¤æ¶å°æåºå¼å¸¸
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;
//å¨ doInBackground() æ¹æ³ä¹å被è°ç¨ï¼ç¨äºåä¸äºçé¢å±çåå¤å·¥ä½
onPreExecute();
//æ§è¡èæ¶ä»»å¡
mWorker.mParams = params;
exec.execute(mFuture);
return this;
}
//ç´æ¥æ§è¡ Runnable æåçä»»å¡ï¼ä¸ä¼è§¦åå个æ½è±¡æ¹æ³
@MainThread
public static void execute(Runnable runnable) {
sDefaultExecutor.execute(runnable);
}
//è¿è¡äºå·¥ä½çº¿ç¨ï¼æ¤æ¹æ³ç¨äºæ´æ°ä»»å¡çè¿åº¦å¼
//ä¼è§¦å onProgressUpdate() 被æ§è¡
@WorkerThread
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
//å°ä¸è¿åº¦å¼ç¸å
³çåæ° Progress å
è£
å° AsyncTaskResult 对象å½ä¸ï¼å¹¶ä¼ éç» Handler è¿è¡å¤ç
getHandler().obtainMessage(MESSAGE_POST_PROGRESS, new AsyncTaskResult