官方文档:
https://developer.android.com/reference/android/os/AsyncTask.html
AsyncTask是一个封装了Thread和Handler的帮助类。使用该类,我们无需自行操作Thread和Handler,就可以完成后台任务处理,并将结果返回到主线程。
先来看AsyncTask类的声明:
可以看到,AsyncTask定义了三个泛型类型参数Params,Progress,Result。各参数含义如下:
(1).Params,执行任务需要使用的参数。
(2).Progress,当前任务执行的进度。
(3).Result,任务执行完成返回的结果。
如果某一个类型不需要传入参数时,可以使用Void类型:
在使用中,主要重写的有以下几个方法:
(1).void onPreExecute(),主线程中执行,在任务执行之前,该方法会被回调。
(2).Result doInBackground(Params... params),该方法在子线程中执行,用来处理耗时操作,不能在这里更新UI。
(3).void onProgressUpdate(Progress... values),主线程中执行,显示当前任务执行的进度。
(4).void onPostExecute(Result result),主线程中执行,任务执行完成之后,该方法被回调,参数即是执行任务返回的结果。
使用AsyncTask时,必须要重写doInBackground(Params... params)方法,因为该方法是abstract的。其余的方法是否需要重写,根据自身的功能需求来决定。一般来说,会同时重写onPostExecute(Result result)方法。
AsyncTask的实现类示例代码如下:
AsyncTask的执行,经过四个步骤:
1.onPreExecute(),当AsyncTask在UI线程上启动任务后,该方法立即执行。这方法通常用于做一些初始化设置,例如在显示一个进度条。
2.doInBackground(Params...),当onPreExecute()执行完成后,该方法立即调用。这方法用于执行耗时操作。execute()方法的参数会传到这里,执行的结果必须在这步返回。在执行过程中,可以调用publishProgress(Progress...)来更新任务的进度。
3.onProgressUpdate(Progress...),当publishProgress(Progress...)执行后,该方法被回调。该方法用于当后台任务还在进行时,在用户界面显示进度。
4.onPostExecute(Result), 当任务执行完成,执行的结果会作为一个参数传递到该方法。我们可以在该方法中刷新UI。
在使用AsyncTask时需要注意以下几点:
(1).必须在主线程中创建AsyncTask对象。
(2).execute(Params... params)方法必须在主线程中调用。
(3).不要手动调用onPreExecute(),onPostExecute(Result),doInBackground(Params...),onProgressUpdate(Progress...)方法。
(4).创建一个AsyncTask对象,只能调用一次execute()方法。
AsyncTask在首次推出时,任务是在单个子线程中串行的执行。从Android 1.6版本开始,AsyncTask内部使用一个线程池,并允许多个任务同时执行。再到Android 3.0版本,AsyncTask被再一次修改,在单线程中执行任务,以避免并行执行引发的应用错误。
如果我们想并行执行任务,可以调用executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,Params... params)方法。
下面我们从执行流程上对AsyncTask核心部分源码进行分析,这里以最新的Android6.0版本为例。
首先,创建AsyncTask对象,并调用其execute(Params... params)方法。
方法内部只有一行,调用了executeOnExecutor(Executor exec, Params... params)方法。
我们再来看看mWorker和mFuture对象。当AsyncTask对象被创建时,会调用其构造方法。
进入postResult()方法,这里看到了我们熟悉的Handler和Message。
接下来,我们找到Handler类。
可以看到,InternalHandler类接收两种消息,MESSAGE_POST_RESULT和MESSAGE_POST_PROGRESS。当InternalHandler接收到进度通知的消息MESSAGE_POST_PROGRESS时,会执行 onProgressUpdate()方法。接收到任务执行完毕返回结果的消息时,会执行finish()方法。
我们再来看看finish()方法。
可以看到,在finish()内部, onPostExecute()方法被执行。
到这里,大致流程已基本结束。我们再回到executeOnExecutor()方法的最后一行,exec.execute(mFuture)。这里的exec其实就是成员变量sDefaultExecutor。
sDefaultExecutor是SerialExecutor类的实例,内部定义了一个任务队列,当调用其execute()方法,会将任务加入队列。每取出一个任务,加入THREAD_POOL_EXECUTOR线程池中执行。当一个任务执行完毕之后,通过scheduleNext()方法再去执行下一个任务。
https://developer.android.com/reference/android/os/AsyncTask.html
AsyncTask是一个封装了Thread和Handler的帮助类。使用该类,我们无需自行操作Thread和Handler,就可以完成后台任务处理,并将结果返回到主线程。
先来看AsyncTask类的声明:
package android.os;
public abstract class AsyncTask<Params, Progress, Result> {
}
可以看到,AsyncTask定义了三个泛型类型参数Params,Progress,Result。各参数含义如下:
(1).Params,执行任务需要使用的参数。
(2).Progress,当前任务执行的进度。
(3).Result,任务执行完成返回的结果。
如果某一个类型不需要传入参数时,可以使用Void类型:
private class MyTask extends AsyncTask<Void, Void, Void> { ... }
在使用中,主要重写的有以下几个方法:
(1).void onPreExecute(),主线程中执行,在任务执行之前,该方法会被回调。
(2).Result doInBackground(Params... params),该方法在子线程中执行,用来处理耗时操作,不能在这里更新UI。
(3).void onProgressUpdate(Progress... values),主线程中执行,显示当前任务执行的进度。
(4).void onPostExecute(Result result),主线程中执行,任务执行完成之后,该方法被回调,参数即是执行任务返回的结果。
使用AsyncTask时,必须要重写doInBackground(Params... params)方法,因为该方法是abstract的。其余的方法是否需要重写,根据自身的功能需求来决定。一般来说,会同时重写onPostExecute(Result result)方法。
AsyncTask的实现类示例代码如下:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
然后调用AsyncTask对象的execute(Params... params)方法启动任务。
AsyncTask的执行,经过四个步骤:
1.onPreExecute(),当AsyncTask在UI线程上启动任务后,该方法立即执行。这方法通常用于做一些初始化设置,例如在显示一个进度条。
2.doInBackground(Params...),当onPreExecute()执行完成后,该方法立即调用。这方法用于执行耗时操作。execute()方法的参数会传到这里,执行的结果必须在这步返回。在执行过程中,可以调用publishProgress(Progress...)来更新任务的进度。
3.onProgressUpdate(Progress...),当publishProgress(Progress...)执行后,该方法被回调。该方法用于当后台任务还在进行时,在用户界面显示进度。
4.onPostExecute(Result), 当任务执行完成,执行的结果会作为一个参数传递到该方法。我们可以在该方法中刷新UI。
在使用AsyncTask时需要注意以下几点:
(1).必须在主线程中创建AsyncTask对象。
(2).execute(Params... params)方法必须在主线程中调用。
(3).不要手动调用onPreExecute(),onPostExecute(Result),doInBackground(Params...),onProgressUpdate(Progress...)方法。
(4).创建一个AsyncTask对象,只能调用一次execute()方法。
AsyncTask在首次推出时,任务是在单个子线程中串行的执行。从Android 1.6版本开始,AsyncTask内部使用一个线程池,并允许多个任务同时执行。再到Android 3.0版本,AsyncTask被再一次修改,在单线程中执行任务,以避免并行执行引发的应用错误。
如果我们想并行执行任务,可以调用executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,Params... params)方法。
下面我们从执行流程上对AsyncTask核心部分源码进行分析,这里以最新的Android6.0版本为例。
首先,创建AsyncTask对象,并调用其execute(Params... params)方法。
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
方法内部只有一行,调用了executeOnExecutor(Executor exec, Params... 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;
exec.execute(mFuture);
return this;
}进入方法之后,首先有if判断,从这里可以看出为什么一个AsyncTask对象只能调用一次execute()方法。然后,把状态置为RUNNING,执行
onPreExecute(),将传入的参数赋值给mWorker.mParams,接下来使用sDefaultExecutor对象执行mFuture。
我们再来看看mWorker和mFuture对象。当AsyncTask对象被创建时,会调用其构造方法。
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*/
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
Result result = doInBackground(mParams);
Binder.flushPendingCommands();
return postResult(result);
}
};
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);
}
}
};
}
在构造方法中,创建一个实现了WorkerRunnable抽象类的对象mWorker,并在其call()方法中,执行doInBackground()方法,将参数mParams传入进去。doInBackground()方法执行完毕后,返回postResult(result)的执行结果。另外创建了一个将要执行的任务FutureTask赋值给mFuture变量,并将上述mWorker传入进去。
进入postResult()方法,这里看到了我们熟悉的Handler和Message。
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
接下来,我们找到Handler类。
private static class InternalHandler extends Handler {
public InternalHandler() {
super(Looper.getMainLooper());
}
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
public void handleMessage(Message msg) {
AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
// There is only one result
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
可以看到,InternalHandler类接收两种消息,MESSAGE_POST_RESULT和MESSAGE_POST_PROGRESS。当InternalHandler接收到进度通知的消息MESSAGE_POST_PROGRESS时,会执行 onProgressUpdate()方法。接收到任务执行完毕返回结果的消息时,会执行finish()方法。
我们再来看看finish()方法。
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
可以看到,在finish()内部, onPostExecute()方法被执行。
到这里,大致流程已基本结束。我们再回到executeOnExecutor()方法的最后一行,exec.execute(mFuture)。这里的exec其实就是成员变量sDefaultExecutor。
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
public static final Executor THREAD_POOL_EXECUTOR
= new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
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);
}
}
}
sDefaultExecutor是SerialExecutor类的实例,内部定义了一个任务队列,当调用其execute()方法,会将任务加入队列。每取出一个任务,加入THREAD_POOL_EXECUTOR线程池中执行。当一个任务执行完毕之后,通过scheduleNext()方法再去执行下一个任务。
本文详细介绍了Android中的AsyncTask类,包括其工作原理、使用方法及注意事项。AsyncTask是Android提供的一个帮助类,它简化了线程和Handler的使用,使得开发者能够轻松地执行后台任务并更新UI。
1192

被折叠的 条评论
为什么被折叠?



