大家都用过AsyncTask,也都知道通过AsyncTask可以比较方便的从事异步操作,并且可以随时更新UI,是一个比较理想的异步事物处理方案。
AsyncTask是如何执行的?
所有人都会告诉我 execute,谁不知道啊!
我最近就遇到了一个问题,通过AsyncTask execute方法,进行异步操作,可是等了好久,doInBackground 也没有执行,更别提操作的结果了。为啥呢?
自己动手,丰衣足食,还是来找源码吧。
首先来看execute的方法体
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
遇到方法重载了,其中sDefaultExecutor 应该是个线程池,我们看一下这个线程池
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
/**
* An {@link Executor} that executes tasks one at a time in serial
* order. This serialization is global to a particular process.
*/
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
在继续跟进SerialExecutor
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
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);
}
}
}
在结合代码,不难发现,这个东西是(SerialExecutor)个假的线程池,实际上顺序执行的,当上一个task未执行完,就不会执行下一个。换句话说,这是一个队列(先入先出),前面的没与执行完,后面的是不会被执行的。所以,当任务多的时候,新建的任务会被延后,所以等待的时间就会变长。
那你可能说,即使有一个队列,但对我new一个AysncTask有影响吗?
有的,因为sDefaultExecutor是AsyncTask的 static 属性,是所有AsyncTask对象共享的,故当使用AsyncTask execute方法的情况下,都可能出现这样的问题。
那应该怎么解决呢?
其实AsyncTask里面真的有一个线程池,只要我们在执行异步任务的时候,使用这个真正的线程池,就可以解决这个问题。
在调用时使用如下方法即可
executeOnExecutor(Executor exec, Params... params)
exec对象使用AsyncTask.THREAD_POOL_EXECUTOR
参考示例如下(假设params 参数类型为String)
execteOnExcecutor(AsyncTask.THREAD_POOL_EXECUTOR,“cbl”)
好了,此篇到此为止了,希望能帮助朋友们解决实际问题