AsyncTask源码分析
来源:互联网 发布:蚂蚁金服规模 知乎 编辑:程序博客网 时间:2024/04/29 23:34
AsyncTask类是我们在开发中经常需要用到的一个类,这个类有个最大的好处就是将耗时的操作和UI操作分开来处理,这样在这一个类中我们就可以很方便的处理耗时操作和UI操作了。
先上一个简单的例子来看看基本的用法。
public class MainActivity extends AppCompatActivity { private ImageView mImageView; private static final String URLSTRING = "https://img3.doubanio.com/view/photo/photo/public/p2360705951.jpg"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mImageView = (ImageView) this.findViewById(R.id.imageview); new MyAsyncTask().execute(); } class MyAsyncTask extends AsyncTask<Void, Integer, Bitmap> { @Override protected Bitmap doInBackground(Void... voids) { URL url = null; HttpURLConnection conn = null; ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { url = new URL(URLSTRING); conn = (HttpURLConnection) url.openConnection(); if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { InputStream ins = conn.getInputStream(); int length = 0; byte[] data = new byte[1024]; while ((length = ins.read(data, 0, data.length)) != -1) { bos.write(data, 0, length); } byte[] buffer = bos.toByteArray(); return BitmapFactory.decodeByteArray(buffer, 0, buffer.length); } } catch (Exception e) { e.printStackTrace(); } finally { conn.disconnect(); try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } return null; } @Override protected void onPostExecute(Bitmap bitmap) { mImageView.setImageBitmap(bitmap); } }}
这个例子很简单,就是加载一个网络图片,并且显示到ImageView上去。
效果如下:
下面源码的分析也从如何操作耗时操作和如何操作UI操作两个方面来分析AsyncTask。
- 耗时操作
对于耗时操作,AsyncTask内部是使用ThreadPool线程池来操作的。直接上源码
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); private static final int CORE_POOL_SIZE = CPU_COUNT + 1; private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1; private static final int KEEP_ALIVE = 1; 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); /** * An {@link Executor} that can be used to execute tasks in parallel. */ public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
CPU_COUNT、CORE_POOL_SIZE、MAXIMUM_POOL_SIZE、KEEP_ALIVE这些常量包含了cpu数量、线程池数量、最大线程池数量、同时或者的最多的线程数量,这些都是用于构造线程池执行器的参数。sThreadFactory是一个线程构造器,sPoolWorkQueue是一个容量为128的阻塞队列。这些参数最后构造了THREAD_POOL_EXECUTOR,通过这个线程池执行器,耗时的任务就可以通过阻塞队列依次的被执行。
- UI线程操作
UI线程的操作是通过构造了一个关联UI线程的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; } } }
在InternalHandler类的构造方法中,传递一个Looper.getMainLooper()参数,就可以将这个Handler关联到UI线程上,所有Handler中的处理也就分发到了UI线程上。所以我们可以利用这个Handler来执行UI操作。
现在我们可以大致得出一个结论:耗时的操作是通过线程池THREAD_POOL_EXECUTOR执行的;UI的操作是通过InternalHandler类操作的。
对于AsyncTask的使用最简单的莫过于上面的new MyAsyncTask().execute(),这个调用涉及到构造方法和executor()两个方法,下面就通过这两个方法的执行来彻底梳理一下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); } } }; }
从代码中可以看到,在构造方法中,生成了一个WorkRunnable对象,WorkRunnable这个类实际上就是一个实现了Callable接口的抽象类,在call()方法中,我们调用了doInBackground()方法,并且将最终的结果通过postResult()分发出去;Callable接口并不是我们需要的,因为线程池需要Runnable的接口,所以又生成了一个FutureTask的对象用来将Callable接口转换成Runnable接口。所以构造方法的目的是生成一个mFuture的FutureTask对象。
- executor方法
executor方法最后调用的executeOnExecutor()方法,我们看源码:
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),exec就是sDefaultExecutor,最终调用了线程池ThreadPoolExecutor中的executor方法执行doInBackground方法,并且在这个方法执行完毕之后调用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方法调用了internalHandler中的消息处理。
case MESSAGE_POST_RESULT: // There is only one result result.mTask.finish(result.mData[0]); break;
result.mTask指的就是AsynTask这个对象,结果就是调用了finish()方法。
private void finish(Result result) { if (isCancelled()) { onCancelled(result); } else { onPostExecute(result); } mStatus = Status.FINISHED; }
最后执行了onPostExecute()这个方法,并且是通过InternalHandler在UI线程完成的。
最后总结一下:在构造方法中,将doInBackground()方法最终包装成一个FutureTask类,然后通过 execute()方法,将这个方法传递到线程池中执行;等执行完毕之后,通过InternalHandler将这个结果发送到AsyncTask的finish()方法中执行,在finish方法中执行onPostExecutor()方法。大致流程就是这样~~
- AsyncTask 源码分析
- AsyncTask源码分析
- Android AsyncTask源码分析
- Android源码分析--AsyncTask
- 源码分析Android AsyncTask
- Android AsyncTask源码分析
- AsyncTask源码分析
- Android-AsyncTask源码分析
- 源码分析--AsyncTask
- AsyncTask源码分析
- AsyncTask源码分析
- AsyncTask源码分析
- AsyncTask源码分析
- Android AsyncTask 源码分析
- AsyncTask源码分析
- AsyncTask源码分析
- AsyncTask源码分析
- AsyncTask源码分析
- 基于iTextSharp(C#)创建PDF文件
- 第一次博客
- 在静态库下使用MFC和共享DLL下使用MFC 这两种情况 opencv的配置,以及配置opencv配置中容易出现的问题
- 从输入url到页面加载完的过程中都发生了什么事情
- c++抽象类
- AsyncTask源码分析
- acm学习报告
- const指针的用法
- Java 简介和开发环境
- 同网段和不同网段设备通信原理详解
- MySql数据库基本操作练习
- 详细分享UICollectionView的自定义布局(瀑布流, 线性, 圆形...)
- Bitmap
- CSS Position属性的学习