AsyncTask源码分析
来源:互联网 发布:科幻片 知乎 编辑:程序博客网 时间:2024/05/18 16:38
Sun式源码分析步骤:
1、这个东西怎么用?
(1)定义具体的AsyncTask
/** * 三个参数传入的参数 AsyncTask<Params, Progress, Result>:要处理的数据类型,进度更新的类型(对应onProgressUpdate()),处理结果的类型 */ class MyTask extends AsyncTask<String, Integer, String> { private TextView textView; public MyTask(TextView textView) { this.textView = textView; } //在execute(Params... params)被调用后立即执行,一般用来在执行后台任务前对UI做一些标记 @Override protected void onPreExecute() { dialog.setTitle("请稍等"); dialog.setMessage("网页正在加载中。。。"); dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); dialog.setButton(DialogInterface.BUTTON_NEUTRAL, "取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); //取消任务 MyTask.this.cancel(true); } }); dialog.show(); } //在onPreExecute()完成后立即执行,用于执行较为费时的操作,此方法将接收输入参数和返回计算结果。在执行过程中可以调用publishProgress(Progress... values)来更新进度信息。 @Override protected String doInBackground(String... params) { int i = 10; while (true) { publishProgress((int) i); if (i == 0) break; try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } i--; } return null; } //在调用publishProgress(Progress... values)时,此方法被执行,直接将进度信息更新到UI组件上 @Override protected void onProgressUpdate(Integer... values) { textView.setText(values + ""); super.onProgressUpdate(values); } // 任务执行的结果作为此方法的返回参数result其实是doInBackgSround(Object... params)的返回值 @Override protected void onPostExecute(String s) { super.onPostExecute(s); } }
(2)启动Task
new MyTask(tv).execute("");
2、找到分析的切入点:这句启动代码就是我们的切入点,开始源码分析
new了一个对象,那么就必定途径构造函数。子类MyTask构造函数没啥分析的,那么就轮到父类AsyncTask的构造函数了。
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); } } }; }
mWorker、mFuture是啥?mWorker是一个实现Callable接口的抽象类。Callable+FutureTask+ThreadPoolExecutor就是多线程的第三种实现方式(另外两种是:Thread、Runnable)
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> { Params[] mParams; }
mWorker=Callable,mFuture=FutureTask,那ThreadPoolExecutor在哪?Look below!
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4)); private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1; private static final int KEEP_ALIVE_SECONDS = 30; private static final ThreadFactory sThreadFactory = new ThreadFactory() { private final AtomicInteger mCount = new AtomicInteger(1); public Thread newThread(Runnable r) { return new Thread(r, "AsyncTask #" + mCount.getAndIncrement()); } }; private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(128); public static final Executor THREAD_POOL_EXECUTOR; static { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory); threadPoolExecutor.allowCoreThreadTimeOut(true); THREAD_POOL_EXECUTOR = threadPoolExecutor; } public static final Executor SERIAL_EXECUTOR = new SerialExecutor(); private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; private static class SerialExecutor implements Executor { //ArrayDeque是数组队列,offer()代表插入元素,poll()代表取出并移除头元素(pop()只是取出) 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); } } }
这么多的代码就是创建一个线程池。致此,new MyTask的过程就结束了,就是为了凑齐Callable+FutureTask+ThreadPoolExecutor三大将来完成多线程的准备。
接下来分析.execute(“”)这部分。
public final AsyncTask<Params, Progress, Result> execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params); }
简单易懂, sDefaultExecutor就是之前创建的那个线程池调度器,传入executeOnExecutor方法。
@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; }
我们可以看到,出现在我们的眼前的便是第一个覆写的函数onPreExecute(),这个函数主要是用来进行一些预处理操作的,它运行在主线程。紧接着,mWork接受传入的参数。然后线程池开始执行mFuture。那么我们再次回到mFuture这段代码。
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); } } };
mFuture的执行传入的mWorker。而mWork中就正式开始执行doInBackground(mParams),这个方法就是运行在非UI线程的,你可以覆写此方法,进行一些耗时操作,然后result获得到了该方法的运行结果,并通过postResult方法将结果传出去,接下来看postResult方法。
private Result postResult(Result result) { @SuppressWarnings("unchecked") Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result)); message.sendToTarget(); return result; }
postResult方法比较好理解,将接收到的结果封装到AsyncTaskResult中,通过消息机制发送出去。那么发送到哪里去了呢?我们看到,是getHandler发送出去的,那么看一下该方法。
private static Handler getHandler() { synchronized (AsyncTask.class) { if (sHandler == null) { sHandler = new InternalHandler(); } return sHandler; } }
我们看到,原来是获取了一个InternalHandler单例,好了,去找InternalHandler吧。
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; } } }
这里,将会对MESSAGE_POST_RESULT进行处理,处理过程是result.mTask.finish(result.mData[0])。result.mTask就是内部包装类AsyncTaskResult中的AsyncTask实例。那么finish就是AsyncTask中的方法,我们来看看它。
private void finish(Result result) { if (isCancelled()) { onCancelled(result); } else { onPostExecute(result); } mStatus = Status.FINISHED; }
可以看到,如果Task已经被取消了,则执行Cancel相关处理,如果没有被取消,则通过onPostExecute方法将结果回调给我们。同样publishProgress方也是通过InternalHandler将进度回调给我们的。
至此,我们就简单的将AsyncTask“运行”了一遍,其中更多的细节,需要自己耐心的去品味了,毕竟我只是想分享一下阅读源码的思维。
- AsyncTask 源码分析
- AsyncTask源码分析
- Android AsyncTask源码分析
- Android源码分析--AsyncTask
- 源码分析Android AsyncTask
- Android AsyncTask源码分析
- AsyncTask源码分析
- Android-AsyncTask源码分析
- 源码分析--AsyncTask
- AsyncTask源码分析
- AsyncTask源码分析
- AsyncTask源码分析
- AsyncTask源码分析
- Android AsyncTask 源码分析
- AsyncTask源码分析
- AsyncTask源码分析
- AsyncTask源码分析
- AsyncTask源码分析
- WORD批量转图片助手v8.6最新版
- Unity Assetbundle的实战
- miniGui中创建多个子窗体及子窗体资源的回收
- 兼容ie8 的 rgba()用法
- UVA 1586 Molar mass
- AsyncTask源码分析
- 关于swift应用中的相关知识记录
- 高流量站点NGINX与PHP-fpm配置优化
- suricata 3.1 源码分析32 (FlowWorker处理流程1)
- Ubuntu12.04异常关机后无法开启的问题解决
- python自动优化之路-day2.1
- Table '**' is marked as crashed and should be repaired的解决方法
- centos7安装eclipse
- Material Design详解