@yudesong
2018-02-12T03:11:24.000000Z
字数 4707
阅读 596
AsyncTask
AsyncTask是一个抽象类,接受三个范型参数:
- Params
在执行AsyncTask时需要传入的参数,可用于在后台任务中使用。
- Progress
后台任务执行时,如果需要在界面上显示当前的进度,则使用这里指定的泛型作为进度单位。
- Result
当任务执行完毕后,如果需要对结果进行返回,则使用这里指定的泛型作为返回值类型。
继承AsyncTask类需要实现如下几个方法:
- onPreExecute()
这个方法会在后台任务开始执行之间调用,用于进行一些界面上的初始化操作,比如显示一个进度条对话框等。
- doInBackground(Params...)
这个方法中的所有代码都会在子线程中运行,我们应该在这里去处理所有的耗时任务。任务一旦完成就可以通过return语句来将任务的执行结果进行返回,如果AsyncTask的第三个泛型参数指定的是Void,就可以不返回任务执行结果。注意,在这个方法中是不可以进行UI操作的,如果需要更新UI元素,比如说反馈当前任务的执行进度,可以调用publishProgress(Progress...)方法来完成。
- onProgressUpdate(Progress...)
当在后台任务中调用了publishProgress(Progress...)方法后,这个方法就很快会被调用,方法中携带的参数就是在后台任务中传递过来的。在这个方法中可以对UI进行操作,利用参数中的数值就可以对界面元素进行相应的更新。
- onPostExecute(Result)
当后台任务执行完毕并通过return语句进行返回时,这个方法就很快会被调用。返回的数据会作为参数传递到此方法中,可以利用返回的数据来进行一些UI操作,比如说提醒任务执行的结果,以及关闭掉进度条对话框等。
实例
class DownloadTask extends AsyncTask<Void, Integer, Boolean> {@Overrideprotected void onPreExecute() {progressDialog.show();}@Overrideprotected Boolean doInBackground(Void... params) {try {while (true) {int downloadPercent = doDownload();publishProgress(downloadPercent);if (downloadPercent >= 100) {break;}}} catch (Exception e) {return false;}return true;}@Overrideprotected void onProgressUpdate(Integer... values) {progressDialog.setMessage("当前下载进度:" + values[0] + "%");}@Overrideprotected void onPostExecute(Boolean result) {progressDialog.dismiss();if (result) {Toast.makeText(context, "下载成功", Toast.LENGTH_SHORT).show();} else {Toast.makeText(context, "下载失败", Toast.LENGTH_SHORT).show();}}}// 启动DownloadTasknew DownloadTask().execute();
接下来分析AsyncTask的源码:
public AsyncTask() {mWorker = new WorkerRunnable<Params, Result>() {public Result call() throws Exception {mTaskInvoked.set(true);Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);return postResult(doInBackground(mParams));}};mFuture = new FutureTask<Result>(mWorker) {@Overrideprotected void done() {try {final Result result = get();postResultIfNotInvoked(result);} catch (InterruptedException e) {android.util.Log.w(LOG_TAG, e);} catch (ExecutionException e) {throw new RuntimeException("An error occured whileexecuting doInBackground()",e.getCause());} catch (CancellationException e) {postResultIfNotInvoked(null);} catch (Throwable t) {throw new RuntimeException("An error occured while executing "+ "doInBackground()", t);}}};}
初始化变量mWorker、mFuture,并且将mWorker作为参数传递给mFuture
接下来分析execute()方法
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 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;}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);}}}void innerRun() {if (!compareAndSetState(READY, RUNNING))return;runner = Thread.currentThread();if (getState() == RUNNING) { // recheck after setting threadV result;try {result = callable.call();} catch (Throwable ex) {setException(ex);return;}set(result);} else {releaseShared(0); // cancel}}public Result call() throws Exception {mTaskInvoked.set(true);Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);return postResult(doInBackground(mParams));}private Result postResult(Result result) {Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,new AsyncTaskResult<Result>(this, result));message.sendToTarget();return result;}private static class InternalHandler extends Handler {@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})@Overridepublic void handleMessage(Message msg) {AsyncTaskResult result = (AsyncTaskResult) msg.obj;switch (msg.what) {case MESSAGE_POST_RESULT:// There is only one resultresult.mTask.finish(result.mData[0]);break;case MESSAGE_POST_PROGRESS:result.mTask.onProgressUpdate(result.mData);break;}}}private void finish(Result result) {if (isCancelled()) {onCancelled(result);} else {onPostExecute(result);}mStatus = Status.FINISHED;}protected final void publishProgress(Progress... values) {if (!isCancelled()) {sHandler.obtainMessage(MESSAGE_POST_PROGRESS,new AsyncTaskResult<Progress>(this, values)).sendToTarget();}}
参考文献
1.Android AsyncTask完全解析,带你从源码的角度彻底理解
2.Java多线程编程:Callable、Future和FutureTask浅析(多线程编程之四)