简介
一个Android封装好的轻量级异步抽象类,使用的话需要继承并重写部分方法
作用
方便的实现多线程,并能方便的实现主线程与工作线程的通信,并且逻辑都在一个类中,不同于Handler的实现机制在不同的回调中,内部采用线程池管理策略,方便管理
使用介绍
public abstract class AsyncTask<Params, Progress, Result> { .... }
可以看到有三个泛型参数,它们的作用分别是:
Params 传递给异步任务的参数类型,对应execute()方法和doInBackground()中的参数类型
Progress 进度跟新参数类型,对应onProgressUpdate()方法返回的参数类型
Result 异步任务执行完毕的返回结果类型,对应doInBackground()方法的返回结果类型和onPostExecute()方法的参数类型
如果不需要使用到,则可以使用Void
类代替
简单示例:
申明一个实现类TestAsyncTask,主要打印方法的执行顺序以及参数及运行的线程名称
/** * Created by hj on 2018/12/29. * 说明: */public class TestAsyncTask extends AsyncTask<String,Integer,Integer> { @Override protected void onPostExecute(Integer integer) { super.onPostExecute(integer); Log.i("HJ","onPostExecute方法接收的参数值:"+integer+"--"+runThreadName()); } @Override protected void onPreExecute() { super.onPreExecute(); Log.i("HJ","onPreExecute"+"--"+runThreadName()); } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); Log.i("HJ","onProgressUpdate:"+ Arrays.toString(values)+"--"+runThreadName()); } @Override protected Integer doInBackground(String... strings) { Log.i("HJ","doInBackground()"+"--"+runThreadName()); publishProgress(50); return 1; } private String runThreadName(){ return "运行在:"+Thread.currentThread().getName()+"线程"; } }
使用:
//必须是在主线程中 TestAsyncTask task = new TestAsyncTask(); task.execute();
打印结果:
I/HJ: onPreExecute--运行在:main线程 I/HJ: doInBackground()--运行在:AsyncTask #1线程I/HJ: onProgressUpdate:[50]--运行在:main线程 I/HJ: onPostExecute方法接收的参数值:1--运行在:main线程
可以看到,只有doInBackground()方法执行在异步线程中,其他的方法都是运行在主线程中,方法执行顺序为:
onPreExecute()---->doInBackground()---->调用publishProgress()方法---->onProgressUpdate()------>onPostExecute()
下面介绍一下方法的具体作用:
onPreExecute 在进行异步任务处理前的一些数据准备工作
doInBackground 处理异步任务逻辑,内部可以调用publishProgress更新进度
onProgressUpdate 进度更新回调
onPostExecute 异步处理完毕后的结果回调 ,处理ui逻辑
源码解析
AsyncTask
内部的实现原理为:线程池+Handler
其内部有两个线程池:
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;public static final Executor THREAD_POOL_EXECUTOR;
SERIAL_EXECUTOR
对应内部的SerialExecutor
内部实现类,主要实现了异步任务的顺序分发:
private static class SerialExecutor implements Executor { final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>(); Runnable mActive; //当前要处理的异步任务 //给execute方法加锁保证了顺序执行 public synchronized void execute(final Runnable r) { //将一个runnable添加进双端队列中 mTasks.offer(new Runnable() { public void run() { try { r.run(); //执行 } finally { scheduleNext(); } } }); if (mActive == null) { scheduleNext(); } } //此方法的作用是将SerialExecutor 池中的任务的第一个任务赋值给mActive ,并压入到 //THREAD_POOL_EXECUTOR线程池中 protected synchronized void scheduleNext() { //poll()方法的作用是删除队列中的第一个并返回结果,如果为null则返回null if ((mActive = mTasks.poll()) != null) { //将第一个任务添加到THREAD_POOL_EXECUTOR线程池中 THREAD_POOL_EXECUTOR.execute(mActive); } } }
而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 AsyncTask(@Nullable Looper callbackLooper) { //初始化一个Handler处理主线程的通信 mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper() ? getMainHandler() : new Handler(callbackLooper); //初始化一个可以存储Params参数的callable实现,其实也是 //THREAD_POOL_EXECUTOR.execute()的执行回调 mWorker = new WorkerRunnable<Params, Result>() { public Result call() throws Exception { //里面的回调是不是很熟悉,和HandlerThread类似 mTaskInvoked.set(true); //添加线程标识,用于postResultIfNotInvoked方法的检查 Result result = null; //这就是onPostExecute()方法的result try { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); //noinspection unchecked result = doInBackground(mParams); //doInBackground方法在这里执行了 Binder.flushPendingCommands(); } catch (Throwable tr) { mCancelled.set(true); //抛异常了取消任务 throw tr; } finally { postResult(result); //此方法的作用是将结果发送到主线程 } return result; } }; //初始化一个Future回调,主要用于检查处理结果是否发送 mFuture = new FutureTask<Result>(mWorker) { //done()方法是在callable()方法之后的回调 @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); } } }; }//mWorker 的实现 private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> { Params[] mParams; //保存传入的参数 }
接下来看看以上检查的方法的实现:
private void postResultIfNotInvoked(Result result) { //执行了mWorker 里的call()回调的都会变为true,如果为false,说明任务没有被执行 final boolean wasTaskInvoked = mTaskInvoked.get(); if (!wasTaskInvoked) { postResult(result); } } //将此AsyncTask对象作为message参数发送,接收到之后就会调用finish()方法结束 private Result postResult(Result result) { @SuppressWarnings("unchecked") Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result)); message.sendToTarget(); return result; }
其中的getHandler()中的Handler的实现类是InternalHandler
,来看看它的实现:
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.mData[0]就是从postResult发送过来的AsyncTask对象 result.mTask.finish(result.mData[0]); //处理结果分发,回调对应的方法 break; case MESSAGE_POST_PROGRESS: result.mTask.onProgressUpdate(result.mData); //这里处理进度更新 break; } } } 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; }
最后来看一下执行方法execute()
:
@MainThread public final AsyncTask<Params, Progress, Result> execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params); } @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; //mWorker中的参数是在这里保存的 exec.execute(mFuture); //将mFuture对象添加到THREAD_POOL_EXECUTOR 线程池中,mFuture在构造方法中做了初始化。 return this; }
总结:
1.初始化两个线程池,一个负责任务调度(SerialExecutor)
,一个负责任务处理THREAD_POOL_EXECUTOR
2.构造方法中实例化了子线程中的callable接口方法,从WorkerRunnable
中取出Params
对象并赋值给dodoInBackground(mParams)
方法执行耗时任务。
3.执行execute()
方法将任务提交到THREAD_POOL_EXECUTOR线程池中,并将Params参数赋值到了WorkerRunnable
中。
4.调用了postResult(result)
,通过InternalHandler 将消息回调到了主线程(执行了finish()方法,里面有onPostExecute方法),实现了UI的更新
作者:我是黄教主啊
链接:https://www.jianshu.com/p/26c359715750