轻量级异步类,是个抽象类
处理异步消息有很多方式,为何存在AsyncTask?
第一点,UI线程不能进行过多的耗时操作,容易引起ANR
第二点,只能在UI线程中去更新UI
第三点,AsyncTask封装了 Handler+Runnable,方便使用
代码实现
MyAsyncTask mTask = new MyAsyncTask();
mTask.execute();
class MyAsyncTask extends AsyncTask<String,Integer,String>{
// 方法:doInBackground()
// 作用:接收输入参数、执行任务中的耗时操作、返回 线程任务执行的结果
@Override
protected String doInBackground(String... strings) {
try {
int count = 0;
int length = 1;
while (count<99) {
count += length;
// 可调用publishProgress()显示进度, 之后将执行onProgressUpdate()
publishProgress(count);
// 模拟耗时任务
Thread.sleep(50);
}
}catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
// 方法:onPostExecute()
// 作用:接收线程任务执行结果、将执行结果显示到UI组件
@Override
protected void onPostExecute(String s) {
// 执行完毕后,则更新UI
mTextMessage.setText("加载完毕");
}
// 方法:onPreExecute()
// 作用:执行 线程任务前的操作
@Override
protected void onPreExecute() {
mTextMessage.setText("加载中");
}
// 方法:onProgressUpdate()
// 作用:在主线程 显示线程任务执行的进度
@Override
protected void onProgressUpdate(Integer... progresses) {
mProgressBar.setProgress(progresses[0]);//progressBar
mTextMessage.setText("loading..." + progresses[0] + "%");
}
}
实现原理
mTask.execute(); 从执行开始查看
// 类中参数为3种泛型类型
// 整体作用:控制AsyncTask子类执行线程任务时各个阶段的返回类型
// 具体说明:
// a. Params:开始异步任务执行时传入的参数类型,对应excute()中传递的参数
// b. Progress:异步任务执行过程中,返回下载进度值的类型
// c. Result:异步任务执行完成后,返回的结果类型,与doInBackground()的返回值类型保持一致
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
sDefaultExecutor这个参数是干什么的?查找之后发现SerialExecutor线程池。再往下分析
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
if (mStatus != Status.PENDING) {//判断当前的AsyncTask是否正在运行,如果正在运行就抛出异常
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(); //调用onPreExecute()执行初始化操作,说明该方法是最早运行的
mWorker.mParams = params; //参数
exec.execute(mFuture); //mFuture 这玩意又是什么东西
return this;
}
public class FutureTask<V> implements RunnableFuture<V> {
public interface RunnableFuture<V> extends Runnable, Future<V> {
由此可知,是线程池里面执行了execute方法,参数实现了Runnable 接口
看看到底SerialExecutor线程池execute 方法干了什么
private static class SerialExecutor implements Executor {
//双向队列
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
// execute()被同步锁synchronized修饰
// 即说明:通过锁使得该队列保证AsyncTask中的任务是串行执行的
// 即 多个任务需1个个加到该队列中;然后 执行完队列头部的再执行下一个,以此类推
public synchronized void execute(final Runnable r) {
//将FutureTask的对象传入
//向队列中加一个新的任务
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 final int CPU_COUNT = Runtime.getRuntime().availableProcessors();//获取cup核心数
private static final int CORE_POOL_SIZE = CPU_COUNT + 1; //设置线程池的核心数2-4,取决于cpu核心数
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;//设置线程池中线程数的最大值cpu*2 +1
private static final int KEEP_ALIVE = 1; //设置线程池线程保活状态
//初始化线程数量
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());
}
};
//初始化任务队列为LinkedBlockingQueue 最大容量128
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);
/**
* An {@link Executor} that can be used to execute tasks in parallel.
*/
public static final Executor THREAD_POOL_EXECUTOR
= new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
由上面可知,做了一系列初始化状态
查看其构造方法
public AsyncTask() {
//初始化WorkerRunnable变量 = 一个可存储参数的Callable对象
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
//表示当前任务已经被执行了
mTaskInvoked.set(true);
//设置线程优先级
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
//在这执行了doInBackground
return postResult(doInBackground(mParams));
}
};
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
//一看我擦,这不是Handler发送消息吗
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
//发送到标记的Handler
message.sendToTarget();
return result;
}
//看一下Handler收消息做了什么
private static class InternalHandler extends Handler {
public InternalHandler() {
//获取的是主线程,所以AsyncTask.execute()必须是在主线程操作
//如果在子线程创建会怎么样( Only the original thread that created a view hierarchy can touch its views报出该异常)
super(Looper.getMainLooper());
}
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
public void handleMessage(Message msg) {
AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
// 若收到的消息 = MESSAGE_POST_RESULT
// 则通过finish() 将结果通过Handler传递到主线程
// There is only one result
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
// 若收到的消息 = MESSAGE_POST_PROGRESS
// 则回调onProgressUpdate()通知主线程更新进度的操作
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
/**
* result.mTask.finish(result.mData[0])
*/
private void finish(Result result) {
// 先判断是否调用了Cancelled()
// 1. 若调用了则执行我们复写的onCancelled()
// 即 取消任务时的操作
if (isCancelled()) {
onCancelled(result);
} else {
// 2. 若无调用Cancelled(),则执行我们复写的onPostExecute(result)
// 即更新UI操作
onPostExecute(result);
}
// 注:不管AsyncTask是否被取消,都会将AsyncTask的状态变更为:FINISHED
mStatus = Status.FINISHED;
}
调用该方法会执行MESSAGE_POST_PROGRESS,返回回调onProgressUpdate
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}
总结:
首先本身会有个线程池提供,调用当前线程池的execute()并在AsyncTask构造开始在WorkerRunnable实例对象时复写的call()方法里,先调用 我们复写的doInBackground(mParams)执行耗时操作,然后调用postResult(result),通过InternalHandler 类 将任务消息传递到主线程;根据消息标识(MESSAGE_POST_RESULT)判断,最终通过finish()调用我们复写的onPostExecute(result),从而实现UI更新操作
AsyncTask 对象execute方法只能调用一次,如果想要调用需要重新new一个AsyncTask对象