关于AsyncTask的用法可以参看前面一篇博客《AsyncTask实现断点续传》,本文只解析AsyncTask的源代码。
AsyncTask.execute方法:
1 public final AsyncTask<Params, Progress, Result> execute(Params... params) { 2 return executeOnExecutor(sDefaultExecutor, params); 3 }
execute方法里面直接调用了executeOnexecute方法。
AsyncTask.executeOnexecute方法:
1 public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, 2 Params... params) { 3 if (mStatus != Status.PENDING) { 4 switch (mStatus) { 5 case RUNNING: 6 throw new IllegalStateException("Cannot execute task:" 7 + " the task is already running."); 8 case FINISHED: 9 throw new IllegalStateException("Cannot execute task:" 10 + " the task has already been executed " 11 + "(a task can be executed only once)"); 12 } 13 } 14 mStatus = Status.RUNNING; 15 onPreExecute(); 16 mWorker.mParams = params; 17 exec.execute(mFuture); 18 return this; 19 }
3-13行是检测AsyncTask的状态,如果状态不为PENDING,则会抛异常,这也是为什么一个AsyncTask只能被执行一次的原因。14行将状态改为RUNNING,表示该任务正在运行。然后调用AsyncTask的onPreExecute()方法。
由下面代码可以看出,AsyncTask有三种状态:PENDING(未运行)、RUNNING(正在运行)、FINISHED(已运行完毕)。
1 public enum Status { 2 /** 3 * Indicates that the task has not been executed yet. 4 */ 5 PENDING, 6 /** 7 * Indicates that the task is running. 8 */ 9 RUNNING, 10 /** 11 * Indicates that {@link AsyncTask#onPostExecute} has finished. 12 */ 13 FINISHED, 14 }
FutureTask代码:
1 public class FutureTask<V> implements RunnableFuture<V> { 2 ...... 3 //构造方法传入一个Callable对象 4 public FutureTask(Callable<V> callable) { 5 if (callable == null) 6 throw new NullPointerException(); 7 this.callable = callable; 8 this.state = NEW; // ensure visibility of callable 9 } 10 public void run() { 11 if (state != NEW || 12 !UNSAFE.compareAndSwapObject(this, runnerOffset, 13 null, Thread.currentThread())) 14 return; 15 try { 16 Callable<V> c = callable; 17 if (c != null && state == NEW) { 18 V result; 19 boolean ran; 20 try { 21 result = c.call();//这里调用了callable.call()方法 22 ran = true; 23 } catch (Throwable ex) { 24 result = null; 25 ran = false; 26 setException(ex); 27 } 28 if (ran) 29 set(result); 30 } 31 } finally { 32 // runner must be non-null until state is settled to 33 // prevent concurrent calls to run() 34 runner = null; 35 // state must be re-read after nulling runner to prevent 36 // leaked interrupts 37 int s = state; 38 if (s >= INTERRUPTING) 39 handlePossibleCancellationInterrupt(s); 40 } 41 } 42 ...... 43 }
AsyncTask构造方法:
1 public abstract class AsyncTask<Params, Progress, Result> { 2 ...... 3 /** 4 * Creates a new asynchronous task. This constructor must be invoked on the UI thread. 5 */ 6 public AsyncTask() { 7 mWorker = new WorkerRunnable<Params, Result>() { 8 public Result call() throws Exception { 9 mTaskInvoked.set(true); 10 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 11 //noinspection unchecked 12 return postResult(doInBackground(mParams)); 13 } 14 }; 15 //创建FutureTask对象的时候传入了mWorker作为Callable 16 mFuture = new FutureTask<Result>(mWorker) { 17 @Override 18 protected void done() { 19 try { 20 postResultIfNotInvoked(get()); 21 } catch (InterruptedException e) { 22 android.util.Log.w(LOG_TAG, e); 23 } catch (ExecutionException e) { 24 throw new RuntimeException("An error occured while executing doInBackground()", 25 e.getCause()); 26 } catch (CancellationException e) { 27 postResultIfNotInvoked(null); 28 } 29 } 30 }; 31 } 32 ...... 33 }
由FutureTask源码我们可以看出,run()方法里面调用了c.call(),而AsyncTask 中创建FutureTask的时候传入了mWorker,所以FutureTask.run()方法里面c.call()调用的是mWorker对象的call()方法,而AsyncTask里mWorker重写了call方法,即上面8-14行,所以c.call()会执行到mWorker.call()方法来。call方法里面11行将线程的优先级设置为后台线程,这样当多个线程并发后很多无关紧要的线程分配的CPU时间将会减少,有利于主线程的处理。
接下来11行执行了doInBackground(mParams)方法,通常我们会重写该方法来实现业务逻辑操作。然后执行postResult方法,并且将结果返回给FutureTask(因为是FutureTask.run方法调用的此call方法,所以需要返回结果到FutureTask.run方法)。这里我们先看看postResult:
1 private Result postResult(Result result) { 2 @SuppressWarnings("unchecked") 3 Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT, 4 new AsyncTaskResult<Result>(this, result)); 5 message.sendToTarget(); 6 return result; 7 }
这里的sHandler是InternalHandler对象。
1 private static class InternalHandler extends Handler { 2 @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"}) 3 @Override 4 public void handleMessage(Message msg) { 5 AsyncTaskResult result = (AsyncTaskResult) msg.obj; 6 switch (msg.what) { 7 case MESSAGE_POST_RESULT: 8 // There is only one result 9 result.mTask.finish(result.mData[0]); 10 break; 11 case MESSAGE_POST_PROGRESS: 12 result.mTask.onProgressUpdate(result.mData); 13 break; 14 } 15 } 16 }
由第9行代码可知最终会执行AsyncTask的finish方法,代码如下:
1 private void finish(Result result) { 2 if (isCancelled()) { 3 onCancelled(result); 4 } else { 5 onPostExecute(result); 6 } 7 mStatus = Status.FINISHED; 8 }
finish的作用是如果task被取消了就执行onCancelled方法,如果没有被取消而是正常执行完毕,则执行onPostExecute方法(这也是为什么task被调用了cancel方法,不会执行onPostExecute的原因)。最后将task的状态标记为FINISHED。
上面说到mWorker.call会将执行结果返回给FutureTask.run()方法并且继续往下执行,我们再次看看FutureTask.run方法(20-30行):
1 boolean ran; 2 try { 3 result = c.call(); 4 ran = true; 5 } catch (Throwable ex) { 6 result = null; 7 ran = false; 8 setException(ex); 9 } 10 if (ran) 11 set(result);
由上面代码可以看到,执行完c.call后,会执行set(result)方法。
1 protected void set(V v) { 2 if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) { 3 outcome = v; 4 UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state 5 finishCompletion(); 6 } 7 }
最终会执行finishCompletion()方法。
1 private void finishCompletion() { 2 // assert state > COMPLETING; 3 for (WaitNode q; (q = waiters) != null;) { 4 if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) { 5 for (;;) { 6 Thread t = q.thread; 7 if (t != null) { 8 q.thread = null; 9 LockSupport.unpark(t); 10 } 11 WaitNode next = q.next; 12 if (next == null) 13 break; 14 q.next = null; // unlink to help gc 15 q = next; 16 } 17 break; 18 } 19 } 20 done(); 21 callable = null; // to reduce footprint 22 }
看到21行代码,会执行FutureTask的done()方法,而这个方法在AsyncTask构造函数中初始化FutureTask对象的时候被重写了。
1 mFuture = new FutureTask<Result>(mWorker) { 2 @Override 3 protected void done() { 4 try { 5 postResultIfNotInvoked(get()); 6 } catch (InterruptedException e) { 7 android.util.Log.w(LOG_TAG, e); 8 } catch (ExecutionException e) { 9 throw new RuntimeException("An error occured while executing doInBackground()", 10 e.getCause()); 11 } catch (CancellationException e) { 12 postResultIfNotInvoked(null); 13 } 14 } 15 };
这里主要是验证postResult是否被调用了,如果没有被调用着调用postResult函数,因为前面mWorker.call方法里面调用过了,所以这里不错操作。
顺便提一下,在AsyncTask的doInBackground方法中如果需要更新UI的话,则调用AsyncTask的publishProgress方法即可:
1 protected final void publishProgress(Progress... values) { 2 if (!isCancelled()) { 3 sHandler.obtainMessage(MESSAGE_POST_PROGRESS, 4 new AsyncTaskResult<Progress>(this, values)).sendToTarget(); 5 } 6 }
publishProgress方法最终也会通过sHandler来调用AsyncTask的onProgressUpdate方法,一般我们如果需要获取进度的话都需要重写AsyncTask的onProgressUpdate。
好了,AsyncTask的源码也分析完了。再次总结一下Asynctask使用的注意事项:
1.异步任务的实例必须在UI线程中创建。
2.execute(Params... params)方法必须在UI线程中调用。
3.不要手动调用onPreExecute(),doInBackground(Params... params),onProgressUpdate(Progress... values),onPostExecute(Result result)这几个方法。
4.不能在doInBackground(Params... params)中更改UI组件的信息。
5.一个任务实例只能执行一次,如果执行第二次将会抛出异常。