AsyncTask 使用
public void test(){
MyAsyncTask myAsyncTask = new MyAsyncTask();
myAsyncTask.execute("");
}
class MyAsyncTask extends AsyncTask<String, Integer, Boolean>{
@Override
protected Boolean doInBackground(String... strings) {
//zi线程操作
return true;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
//ui 线程
}
@Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
//ui 线程上操作
}
}
使用很简单,创建一个类继承AsyncTask
,
- 重写
doInBackground
方法在该方法里做耗时操作 - 重写
onPostExecute
在耗时操作结束后这里会回调到主线程做结果处理操作
myAsyncTask.execute
调用AsyncTask
源码解析
构造函数
public AsyncTask(@Nullable Looper callbackLooper) {
/**
* 初始化mHandler
*/
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
? getMainHandler()
: new Handler(callbackLooper);
/**
* 初始化WorkerRunnable
*/
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
//设置标识让postResultIfNotInvoked方法里不会重复执行
mTaskInvoked.set(true);
Result result = null;
try {
//线程优先级设置后台线程
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//执行doInBackground返回result
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
//异常则取消
mCancelled.set(true);
throw tr;
} finally {
//调用postResult方法
postResult(result);
}
return result;
}
};
/**
* 初始化FutureTask
*/
mFuture = new FutureTask<Result>(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);
}
}
};
}
可以看到构造函数里主要做了三件事
- 初始化
mHandler
,这里会判断是否传入了Looper
如果没有会获取主线程的Looper
所以不传
Looper
时不能在子线程里初始化AsyncTask
- 初始化
WorkerRunnable
,在mWorker
里的call
方法实现了doInBackground
和postResult
(通过handler
调用postResult
方法) - 初始化
FutureTask
executeOnExecutor 方法
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
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;
exec.execute(mFuture);
return this;
}
当我们调用execute
方法时,他会最终调用到executeOnExecutor
方法,并传入一个sDefaultExecutor
线程池(下面讲到)
在executeOnExecutor
方法里会判断这个任务是否已经执行过,如果正在执行中或者已经执行完成则会抛出一个IllegalStateException
异常,如果没有执行过则开始执行onPreExecute
方法,然后向线程池里抛mFuture
任务执行耗时操作
所以
AsyncTask
的execute
方法只能调用一次
两个线程池
AsyncTask
有两个线程池,一个用来执行具体任务,另一个只用作任务排对
//第一个线程池,用作执行具体任务
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;
}
/**
* 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();
private static final int MESSAGE_POST_RESULT = 0x1;
private static final int MESSAGE_POST_PROGRESS = 0x2;
//上述说道
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
可以看到sDefaultExecutor
实则就是SerialExecutor
实例,SerialExecutor
由一个数组结构的双向队列构成,从队列中取出任务后放入THREAD_POOL_EXECUTOR
执行;在execute
方法里可以看到这个线程是个串行任务队列线程池目的就是为了做到排队作用一次只能有一个任务执行。
所以
AsyncTask
的任务是串行的(API3.0以后,3.0之前是并行)
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);
}
}
}
内存泄漏
- 在Activity中使用AsyncTask,AsyncTask持有Activity的引用,如果在网络请求没有结束,但是Activity已经被关闭的情况下,Actuvity的引用的不到释放,就会造成内存泄漏。(解决方法使用弱引用、判断activity等)
- 为什么
cancel
方法不能解决内存泄漏
public final boolean cancel(boolean mayInterruptIfRunning) {
mCancelled.set(true);
return mFuture.cancel(mayInterruptIfRunning);
}
public boolean cancel(boolean mayInterruptIfRunning) {
if (!(state == NEW &&
U.compareAndSwapInt(this, STATE, NEW,
mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
return false;
try { // in case call to interrupt throws exception
if (mayInterruptIfRunning) {
try {
Thread t = runner;
if (t != null)
t.interrupt();
} finally { // final state
U.putOrderedInt(this, STATE, INTERRUPTED);
}
}
} finally {
finishCompletion();
}
return true;
}
可以看到cancel
方法最终不过是调用了FutureTask
的cancel
方法,该方法里只是调用了线程的interrupt
方法,而interrupt
方法不会立马中断一个正在运行的线程,而是发出中断请求然后由线程在一个合适的时刻中断自己。所以他并不能立马中断操作。