对于每个Android应用程序都运行在一个dalvik虚拟机进程中,应用进程开始的时候会启动一个主线程(MainThread),主线程负责处理和ui相关的事件,因此主线程通常又叫UI线程。而由于Android采用UI单线程模型,所以只能在主线程中对UI元素进行操作。并且主线程为我们提供了消息循环的机制,我们可以利用这个机制来实现线程间的通信。那么,我们就可以在非UI线程发送消息到UI线程,最终让Ui线程来进行ui的操作。同时我们也可以实现子线程之间的通信,从而异步执行特定动作。所以当有多个后台任务时且异步任务的数据不太大时,我们自己创建线程来实现就有点复杂了,这时我们就可以使用AsyncTask来完成,它可以创建线程,并且对其进行维护,实现异步消息机制。这就是我们为何要引入AsyncTask机制。
那么什么是AsyncTask机制?如何使用AsyncTask机制?使用AsyncTask机制常见问题有哪些?这是我们大家所关心的,所以本文后面会主要就这几个方面展开来讲解。
AsyncTask是android提供的一种异步消息处理机制,可以直接继承AsyncTask,在类中继承抽象方法执行耗时任务,并且AsyncTask提供接口反馈当前异步操作的进度,可以通过接口实现UI更新。最终返回后台执行的结果给UI主线程,从而实现消息的异步处理。
在使用AsyncTask时我们需要了解一下AsyncTask的三种泛型类型:
1.Params:执行任务所需要的参数,如HTTP请求的URL。
2.Progress:后台任务执行的百分比。
3.Result:后台任务最终执行的返回结果。
在实现AsyncTask时我们一般需要重写如下函数,其中doInBackground为抽象函数我们必须重写外,其余的根据自身需要进行选择性重写。
1)onPreExecute:这个方法会在后台任务执行之前,在UI线程中执行,用于进行界面上的一些初始化,比如显示一个进度条对话框。
2)doInBackground:这个方法是抽象方法子类必须要重写,它的所有代码都会在子线程中运行,我们应该在这去处理所有的耗时任务,在这个方法中是不能进行UI操作的,如果需要更新UI元素,比如说反馈当前任务的执行进度,可以调用publishProgress方法来完成。
3)onProgressUpdate:当在后台任务中调用publishProgress函数时,这个函数就会很快被调用,方法中携带的参数就是后台传输过来的,可以对UI进行操作。
4)onPostExecute:当后台任务执行完毕并将结果返回时就会调用该函数。返回的数据会做为参数传到该函数中,可以利用返回结果进行UI操作,比如提示任务执行的结果,以及关闭对话框。
AsyncTask构造流程
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*/
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() { //创建WorkerRunnable对象
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
Result result = doInBackground(mParams); //当调用call函数时,会执行doInBackground
Binder.flushPendingCommands();
return postResult(result);
}
};
mFuture = new FutureTask<Result>(mWorker) { //创建FutureTask对象
@Override
protected void done() {
try {
postResultIfNotInvoked(get()); //调用done函数时,触发postResultIfNotInvoked
} 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);
}
}
};
}
AsyncTask的构造函数主要做的事情就是创建了mWorker与mFuture,这两个对象中的call函数与done函数非常重要,后面会详细讲解。
当我们创建好AsyncTask后就可以调用它的execute函数或者executeOnExecutor函数,两者的主要区别是execute函数使用的是默认的串行执行器,而executeOnExecutor可以使用并行执行器,也可以自己指定一个执行器。下面重点讲解AsyncTask的串并行执行过程。
串行执行方法
调用execute函数使用的执行器为sDefaultExecutor,即SerialExecutor对象
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecut