what
android 使用模板模式,封装用于执行异步任务。在android中通常情况下需要实现多线程任务以及UI的更新,但是UI通常情况下只能由UI线程来更新,我们一般简单点可能会使用handler啊,runOnUI方法啊,其实本质也是使用UI主线程的handler。但是写起来很好看不方便,所以android使用handler和线程池封装了一个用于执行异步的AsyncTask。
how
首先看看怎么用吧,巨简单。
继承AsyncTask
三泛型代表:
- Params 输入参数类型
- Result 执行结果类型
- Progress 进度量类型
依次重写构造方法:
doInBackground
具体任务执行onPreExecute
任务之前,UI线程,一般用于添加执行开始提示onPostExecute
任务执行之后,UI线程,用于添加执行完成提示onProgressUpdate
进度变化回调,UI线程,用于添加进度提示
1 |
|
新建实例,执行
这个是使用默认线程池,会去排队的哦(串行执行)
1 | new DeleteAsyncTask().execute(mSelectedList); |
你要觉得不爽,或者你的任务很特别是那种IO任务啊,或者计算任务啊。指定你的线程池
1 | new DeleteAsyncTask().executeOnExecutor(executor,mSelectedList); |
why
首先讲下为啥以execute(paramm)
的方式执行AsyncTask是串行的执行的。为啥呢,因为AsyncTask内部是维持了两个线程池,SERIAL_EXECUTOR
:用于任务排队即所有任务顺序执行的线程池。THREAD_POOL_EXECUTOR
:用于实际执行任务的线程池,调用execute时会通过SERIAL_EXECUTOR
来执行,而这个则是入队列,然后调用THREAD_POOL_EXECUTOR
来实际执行任务。对了他们都是静态的。
AsyncTask状态
1 | public enum Status { |
SERIAL_EXECUTOR线程池
1 | private static class SerialExecutor implements Executor { |
THREAD_POOL_EXECUTOR 线程池
1 | public static final Executor THREAD_POOL_EXECUTOR; |
InternalHandler
1 | private static class InternalHandler extends Handler { |
首先从构造方法看
最终都会调用参数为Looper的构造方法,在构造方法里面进行获得UI handler,以及初始化CallAble和FutureTask
1 | public AsyncTask() { |
看execute执行
1 | public final AsyncTask<Params, Progress, Result> execute(Params... params) { |
走向executeOnExecutor,当然我们也可以调,这个就是说让任务在传入的线程池中运行
首先判断标志位是否合格,也就是执行过的或者执行完的都不能再次执行了。回调onPreExecute,然后添加参数进入线程池
1 | public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, |
来到串行线程池
将任务入队列,顺序执行,调用实际的线程池
1 | private static class SerialExecutor implements Executor { |
几个回调
doInBackground
在Callable中执行的
1 | mWorker = new WorkerRunnable<Params, Result>() { |
onPreExecute
在任务进入线程池之前执行
1 | mStatus = Status.RUNNING;//修改状态 |
onPostExecute
handler发送结果后finish中执行
1 | private void finish(Result result) { |
onProgressUpdate
在手动调用publishProgress,handler发送消息
1 | protected final void publishProgress(Progress... values) { |
onCancelled
使用cancel,取消任务
1 | public final boolean cancel(boolean mayInterruptIfRunning) { |