Android中的AsyncTask原理:

在Android开发中,当通过线程去执行耗时的任务,并且在操作完以后可能还会更新UI时,通常还会用Handler类来更新UI线程。总体来说,实现简单,但是如果有多个任务同时执行时则会显得代码臃肿。Android提供了AsyncTask,它使得异步任务实现起来更加简单,代码更简介。


AsyncTask的定义:

public abstract class AsyncTask{……}

由定义可以看出,AsyncTask是一个抽象的泛型类,3个泛型参数。其中参数Params为参数类型。参数Progress为后台任务执行进度的类型。参数Result为返回结果的类型。如果不需要某个参数,可以将其设置为Void类型。
其中,AsyncTask中有4个核心方法:

1.onPreExecute():在主线程中执行。一般在任务执行前做准备工作。例如对UI做一些标记。2.doInBackground(Params...params):在线程池中执行。在onPreExecute方法执行后运行,用来执行较为耗时的操作。在执行过程中可以调用publishProgress(Progress...values)来更新进度信息。3.onProgressUpdate(Progress...values):在主线程中执行。当调用publishProgress(Progress...values)时,此方法会将进度更新在UI组件上。4.onPostExecute(Result result):在主线程中执行。当后台任务执行完成后,它会被执行。doInBackground方法执行得到的结果就是返回的result的值。此方法一般做任务执行后的收尾工作。比如更新UI和数据。

AsyncTask源码分析:
AsyncTask在3.0版本之前后之后有着较大的改动:

  1. Android 3.0版本之前的AsyncTask:(部分源码)
public abstract class AsyncTask{private static final String LOG_TAG="AsyncTask";private static final int CORE_POOL_SIZE=5;private static final int MAXIMUM_POOL_SIZE=128;private static final int KEEP_ALIVE=1;private static final BlockingQueue sWorkQueue=new LinkedBlockingQueue(10) ;private static final ThreadFactory sThreadFactory = new ThreadFactory()}private final AtomicInteger mCount=new AtomicInteger(1);private Thread newThread(Runnable r){return new Thread(r,"AsyncTask #"+mCount.getAndIncrement());}};private static final ThreadPoolExecutor sExecutor=new ThreadPoolExecutor(CORE_POOL_SIZE,MAXIMUM_POOL_SIZE,KEEP_ALIVE,TimeUnit.SECONDS,sWorkQueue,sThreadFactory);…………}

上述源码中,又看到了ThreadPoolExecutor,它的核心线程数是5个,线程池允许创建的最大线程数为128,非核心线程空闲等待新任务的最长时间为1s。采用的阻塞队列是LinkedBlockingQueue,容量是10.对于3.0之前的AsyncTask的一个缺点就是线程池最大的线程数为128,加上阻塞队列的10个任务,AsyncTask最多能同时容纳138个任务,当提交到第139个任务的时候就会执行饱和策略,默认抛出RejectedExecutionException异常。

  1. Android 7.0版本的AsyncTask:
    对于Android 3.0以后的AsyncTask 。首先来看AsyncTask的构造方法。
    AsyncTask的构造方法如下:
public AsyncTask(){mWorker=new WorkerRunnable(){public Result call() throws Exception{mTaskInvoked.set(true);Progress.setThreadPriority(Progcess.THREAD_PRIORITY_BACKGROUND);Result result=doInBackground(mParams);Binder.flushPendingCommands();return postResult(result);}};mFuture=new FutureTask(mWorker){@Overrideprotected 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);}}};}

由上面的源码可以看出,WorkRunnable实现了Callable接口,并是实现了他的call方法,在call方法中调用了doInBackground(mParams)来处理任务并得到结果,并最终调用postResult将结果投递出去。FutureTask是一个可管理的异步任务,它实现了Runnable和Future这2个接口。因此,它可以包装Runnable和Callable,并提供给Executor执行。也可以调用线程直接执行(FutureTask.run())。在这里WorkerRunnable作为参数传递给了FutureTask。这2个 变量会暂时保存在内存中,稍后会用到它们。当要执行AsyncTask时,需要调用它的execute()方法:

public final AsyncTask execute(Params..params){return executeOnExecutor(sDefaultExecutor,params);}

execute方法又调用了executeOnExecutor方法:

public final AsyncTask\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()方法,mWorker.mParams=params;将AsyncTask的参数传给WorkRunnable.从前面知道WorkRunnable作为参数传递给了FutureTask。因此,参数被封装到FutureTask中。接下来会调用exec.的execute方法,并将mFuture也就是前面提到的FutureTask传进去。这里的exec是传进来的参数sDefaultExecutor,它是一个串行的线程池SerialExecutor:

private static class SerialExecutor implements Executor{final ArrayDeque mTasks=new ArrayDeque();Runnable mActive;public synchronized void execute(final Runnable r){public void run(){try{r.run();}finally{scheduleNext();}}};if(mActive==null){scheduleNext();}}protected synchronized void scheduleNext(){if((mActive=mTask.poll())!=null){THREAD_POOL_EXECUTOR.execute(mActive);}}}

上面的mTask.offer(new Runnable){…}中,当调用SerialExecutor的execute方法时,会将Future加入到mTasks中。当任务执行完或者当前没活动的任务时都会执行scheduleNext方法,它会从mTasks取出FutureTask任务并交由THREAD_POOL_EXECUTOR处理。从这里可以看出SerialExecutor是串行执行的。在r.run()处可以看到执行了FutureTask的run方法,它最终会调用WorkerRunnable的call方法。前面提到过call方法最终会调用postResult方法将结果投递出去,postResult方法的代码:

private Result postResult(Result result){@SuppressWarnings("unchecked")Message message=getHandler().obtainMessage(MESSAGE_POST_RESULT,new AsyncTaskResult(this,result));message.sendToTarget();return result;}

在postResult方法中会创建Message,将结果赋值给这个Message,通过getHandler方法得到Handler,并通过这个Handler发送消息。getHandler方法:

private static Handler getHandler(){synchronized(AsyncTask.class){if(sHandler==null){sHandler=new InternalHandler();}return sHandler;}}

在getHandler方法中创建了InternalHandler,InternalHandler的定义如下:

private static class InternalHandler extends Handler{public InternalHandler(){super(Looper.getMainLooper());}@SuppressWarings({"unchecked","RawUseOfParameterizedType"})@Overridepublic void handleMessage(Message msg){AsyncTaskResult<?> result=(AsyncTaskResult<?>) msg.obj;swith(msg.what){case MESSAGE_POST_RESULT://there is only one resultresult.mTask.finish(result.mData[0]);break;case MESSAGE_POST_PROGRESS:result.mTask.onProgressUpdate(result.mData);break;}}}

在收到MESSAGE_POST_RESULT消息后会调用AsyncTask的finish方法:

private void finish(Result result){if(isCancelled){onCancelled(result);}else{onPostExecute(result);}mStatus=Status.FINISHED;}

如果AsyncTask任务被取消了,则执行onCancelled方法,否则调用onPostExecute方法。正是通过onPostExecute方法,我们才能够得到异步任务执行后的结果。接着回头看SerialExecutor,线程池SerialExecutor主要处理排队,将任务串行处理。在SerialExecutor中调用scheduleNext方法时,将任务交给THREAD_POOL_EXECUTOR.THREAD_POOL_EXECUTOR同样是一个线程池,用来处理任务:

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 BlockingQueue sPoolWorkQueue=new LinkedBlockingQueue(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;} 

THREAD_POOL_EXECUTOR指的就是threadPoolExecutor,其核心线程和线程池允许创建的最大线程数是由CPU的核数计算出来的。它采用的阻塞队列仍然是LinkedBlockingQueue,容量为128.


  1. 在AsyncTask中哟个到了线程池,在线程池中运行线程,并且又用到了阻塞队列。Android 3.0以上版本用SerialExecutor作为默认的线程,它将任务串行的处理,保证一个时间段只有一个任务执行。而Android 3.0之前的版本是并行处理的。Android 3.0之前的版本的缺点在3.0以后的版本中也不会出现,因为线程是一个接着一个执行的,不会出现超过任务数而执行饱和策略的情况。如果想要在3.0及其以上版本使用并行的线程处理,可以使用:
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR," ");

其中,asyncTask是我们自定义的AsyncTask,当然也可以传入4种线程池,比如传入CachedThreadPool:

asyncTask.executeOnExecutor(Executors.newCachedThreadPool()," ");

还可以传入自定义的线程池:

Executor exec=new ThreadPoolExecutor(0,Integer.MAX_VALUE,0L,TimeUnit.MILLSENDS,new LinkedBlockingQueue());asyncTask.executeOnExecutor(exec," ");

更多相关文章

  1. android 笔记 --- Android界面刷新的方法
  2. Android(安卓)数据库SQLite的使用简单Demo
  3. android完全退出程序
  4. Android(安卓)APK应用安装原理(1)-解析AndroidManifest原理-Pack
  5. Android(安卓)ButterKnife框架的使用方法
  6. android lru缓存 辅助类LruCache源码解析
  7. Android(安卓)中报错 W/System.err: android.os.NetworkOnMainTh
  8. 浅谈Java中Collections.sort对List排序的两种方法
  9. Python list sort方法的具体使用

随机推荐

  1. ❤️Android(安卓)从源码解读 Apk 的安装过
  2. Android:GridView+AbsoluteLayout作一个
  3. android startService onStartCommand 多
  4. android 布局属性
  5. Android:GridView+AbsoluteLayout作一个
  6. android:onClick事件
  7. Android---inputType参数类型
  8. 常见Theme
  9. android android:taskAffinity 详解
  10. Android附带Theme总结