从源代码理解AsyncTask的工作原理
2016-04-12 15:36
225 查看
首先,我们以AsyncTask的构造器和execute()方法作为研究的切入口;
一.
AsyncTask的构造器主要做了一些准备工作:public AsyncTask() { mWorker = new WorkerRunnable<Params, Result>() { public Result call() throws Exception { mTaskInvoked.set(true); Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); //noinspection unchecked return postResult(doInBackground(mParams)); } }; 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 occured while executing doInBackground()", e.getCause()); } catch (CancellationException e) { postResultIfNotInvoked(null); } } }; }
可以看到,在构造器中就给mWorker和mFuture进行了赋值,这里值得注意的是
1.mWorker中有一个call()方法
2.mWorker的call()中有
postResult(doInBackground(mParams))
2.mWorker作为参数传进mFuture的构造方法中,两者建立了联系
3.mWorker和mFuture中的方法都还没有被调用的
知道这些就可以了
二.
我们看execute(Params...params)方法:public final AsyncTask<Params, Progress, Result> execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params); }注意这里executeOnExecutor的参数传入的是sDefaultExecutor;
显然我们接着看executeOnExecutor(Executor exec , Params...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; }
这里就可以知道onPreExecutor()是在这里被调用的;
然后设置mWorker 的Params参数;
最后调用线程池exec(sDefaultExecutor)来execute(mFuture); 最最重要的部分来了,真正的执行在于这个sDefaultExecutor的execute之中
三.
我们来看这个sDefaultExecutor: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); } } }在这个execute方法中,就执行了前面构造器中赋值了的mFuture(也就是这里的Runnable r.run())中的方法;
又因为mWorker是作为参数传进了mFuture中,于是乎mWorker的call这时也被调用了,换言之,就是call中的postResult()和DoInBackground()被调用了;
注意这里有两个线程池,SerialExecutor只是负责任务的排队,而THREAD_POOL_EXECUTOR才是真正的执行任务;
四.
我们知道在上面postResult()被调用了,那它究竟做了什么呢?private Result postResult(Result result) { @SuppressWarnings("unchecked") Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result)); message.sendToTarget(); return result; }
很简单就是创建并发送message;
五.
然后我们看发送了消息后,Handler做了什么:private static class InternalHandler extends Handler { public InternalHandler() { super(Looper.getMainLooper()); } @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"}) @Override public void More ...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; } }原来就是根据消息内容来调用finish()方法或者调用onProgressUpdate();
private void finish(Result result) { if (isCancelled()) { onCancelled(result); } else { onPostExecute(result); } mStatus = Status.FINISHED; }
而finish()中由会调用onPostExecute(Result result)方法,到这里,asyncTask的四个核心的方法全部出现被调用了;
最后,我们来总结一下整个流程:
1.execute(Params...params)调用executeOnExecutor(Executor exec , Params...params)2.调用了onPreExecute()方法;
3.sDefaultExecutor执行execute()使得mWorker的call()被调用,这时doInBackground()被调用,然后postResult()被调用;
4.在postResult()中发送消息,Handler根据消息调用了onProgressUpdate()或者onPostExecute();
相关文章推荐
- MyEclipse 2015 stable 2.0破解
- 这种代码怎么改写?以致于在下次增加CustomsType时,不需要再加 if 语句。
- C++中 #ifdef 和#endif的作用
- python异常如何全面捕获
- c#中DataTable和DataSet区别
- javase和javaee中获取文件路径的方法总结
- C++临时变量的生命周期
- 百度聚合代码
- 编程之美 1.16 24点游戏
- Python学习
- eclipse手贱配颜色恢复方法
- struts2的struts.xml文件的固定格式
- 有没有一段代码,让你觉得人类的智慧也可以璀璨无比?
- C++著名程序库的比较和学习经验
- VB中IIF函数
- Java判断两个时间是不是同一天
- 深入理解和探究Java类加载机制
- C#之Common
- javac和java命令的详解
- 0基础学C#教程1--------comboBox的相关操作(包括下拉,多数据操作等等)