1.Android引入AsyncTask目的
1.子线程中更新UI
2.封装和简化异步操作
2.构建AsyncTask是一个抽象类,通常用于被继承,继承AsyncTask需要指定如下的三个泛型参数
Params:启动时输入参数的类型
progress:后天任务执行中返回进度值的类型
Result:后台执行完成后返回结果的类型。
3.构建AsyncTask子类的回调方法
doInBackground:必须重写,异步执行后台线程将要完成的任务(必须的方法)
onPreExecute:执行后台耗时操作前被调用,通常用户完成一些初始化操作
onPostExecute:在doInBackground()完成后,系统会自动调用onPostExecute()方法,并将doInBackground方法返回的值传给该方法。
onProgressUpdate:在doInBackground()方法中调用publishProgress()方法更新任务的执行进度
执行顺序:onPreExecute->doInBackground->onPostExecute
如果在doInBackground 中调用publishProgress()方法,则执行顺序是onPreExecute->doInbackground->onProgressUpdate->onPostExecute
例:
public class MyAsyncTask extends AsyncTask {
@Override
protected Void doInBackground(Void... voids) {
Log.v("AAAAA","doInBackground");
publishProgress();
return null;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
Log.v("AAAAA","onPreExecute");
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
Log.v("AAAAA","onPostExecute");
}
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
Log.v("AAAAA","onProgressUpdate");
}
4.AsyncTask注意事项
必须在UI线程中创建AsyncTask的实例
必须在UI线程中调用AsyncTask的execute()方法
重写的四个方法都是系统自动调用的,不应该手动调用
每个AsyncTask只能被执行一次,多次调用将会引发异常
只有doInBackground运行在子线程中,onPreExecute,onPostExecture,onProgressUpdate都运行在主线程中。
5.AsyncTask的实现原理
1.AsyncTask的主要组成
AsyncTask可以看做是对线程池和hanlder进行了一层封装,在对AysncTask初始化时,Async会根据cpu的数量定义线程池中的核心线程数。
ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
由上可以看出创建的线程池本身就是一个固定线程数的线程池
同时创建了一个Hanlder
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// We want at least 2 threads and at most 4 threads in the core pool,
// preferring to have 1 less than the CPU count to avoid saturating
// the CPU with background work
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) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
}
};
private static final BlockingQueue sPoolWorkQueue =
new LinkedBlockingQueue(128);
/**
* An {@link Executor} that can be used to execute tasks in parallel.
*/
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;
}
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static final int MESSAGE_POST_RESULT = 0x1;
private static final int MESSAGE_POST_PROGRESS = 0x2;
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
private static InternalHandler sHandler;
private final WorkerRunnable mWorker;
private final FutureTask mFuture;
private volatile Status mStatus = Status.PENDING;
private final AtomicBoolean mCancelled = new AtomicBoolean();
private final AtomicBoolean mTaskInvoked = new AtomicBoolean();
private final Handler mHandler;
private static class SerialExecutor implements Executor {
final ArrayDeque mTasks = new ArrayDeque();
Runnable mActive;
public synchronized void execute(final Runnable r) {
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);
}
}
2.AsyncTask初始化时,默认会初始化Hanlder
public AsyncTask(@Nullable Looper callbackLooper) {
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);
}
}
};
}
3.当执行AsyncTask::execute()方法时,本质上调用的是线程池进行执行的,同时这个方法是运行在主线程的。
public final AsyncTask execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
@MainThread
public final AsyncTask 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;
}
4.通过Hanlder传递消息
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult(this, result));
message.sendToTarget();
return result;
}
@WorkerThread
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult(this, values)).sendToTarget();
}
}
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:
// There is only one result
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}