标签:
AsyncTask是异步任务,在不阻塞UI线程的情况下,在后台处理复杂逻辑,并将结果返回到UI线程,现在来分析一下AsyncTask的实现。
先来看看我们常见的使用方法。
先声明一个类,继承自AsyncTask。
class MyTask extends AsyncTask<Void,Integer,Integer>{ @Override protected Integer doInBackground(Void... params) { // TODO Auto-generated method stub return null; } }然后使用它
MyTask task; task = new MyTask(); task.execute();具体AsyncTask都做了什么,一步步看。在AsyncTask内部有两个很重要的对象
private final WorkerRunnable<Params, Result> mWorker; private final FutureTask<Result> mFuture;先看看WorkerRunnable
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> { Params[] mParams; }WorkerRunnable继承自Callable,Callable的官方说明是:Callable和Runnable类似,都是可以在另一个线程中执行的,但是二者还是有区别的。
1、Callable的接口方法是call,Runnable是run
2、Callable可以带返回值,Runnable不行
3、Callable可以捕获异常,Runnable不行
public interface Callable<V> { /** * Computes a result, or throws an exception if unable to do so. * * @return computed result * @throws Exception if unable to compute a result */ V call() throws Exception; }再看看FutureTask,FutureTask是异步计算的结果,继承关系是 FutureTask -> RunnableFuture->Runnable, Future,FutureTask内部可以判断任务的执行状态,并切可以取消任务。
FutureTask的构造函数接收一个Callable类型参数,赋值给callable对象
public FutureTask(Callable<V> callable) { if (callable == null) throw new NullPointerException(); this.callable = callable; this.state = NEW; // ensure visibility of callable }
上面的WorkerRunnable被传入,在FutureTask的run方法中,调用WorkerRunnable的call方法执行,并返回结果。
public void run() { ...... try { Callable<V> c = callable; if (c != null && state == NEW) { V result; boolean ran; try { result = c.call(); ran = true; } catch (Throwable ex) { ...... } if (ran) set(result); } } finally { ...... } }
public AsyncTask() { mWorker = new WorkerRunnable<Params, Result>() { public Result call() throws Exception { ...... } }; mFuture = new FutureTask<Result>(mWorker) { @Override protected void done() { ...... } }; }我们看到,之前提到过的两个对象,在这里被创建,mFuture实现了done的重载,就是任务完成后,执行此处代码。当我们执行execute方法是,调用的是下面代码
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; }通过 exec.execute(mFuture); 开始执行任务,execute需要Runnable类型对象,mFuture就是FutureTask类型对象,继承自Runnable。
再看看结果获得后,返回的动作。
在FutureTask中的run方法中通过 callable 开始执行任务,任务结束后,会执行set方法
public void run() { ...... try { Callable<V> c = callable; if (c != null && state == NEW) { ...... if (ran) set(result); } } finally { ...... } }set方法中执行结束任务的方法 finishCompletion,这里就会调用 done 接口,就通知到了AsyncTask的mFuture的done回调
protected void set(V v) { if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) { outcome = v; UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state finishCompletion(); } }
private void finishCompletion() { // assert state > COMPLETING; ...... done(); callable = null; // to reduce footprint }mFuture的done回调中会通过postResultIfNotInvoked调用postResult直接提交结果,那么对于另一个对象mWorker来说,在call回调中,通过postResult(doInBackground(mParams));去提交结果,所以 doInBackground 是我们必须实现的一个接口函数。
postResult中通过内部的一个handler,去通知UI进程,并处理 onPostExecute 及 onProgressUpdate 接口的实现。这样就完成了任务的整个传递。
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/bdmh/article/details/49306155