但凡接触过Android开发的人都知道UI线程是不能进行耗时操作的,否则有可能出现ANR。那么为了避免这个问题Android提供了AsyncTask来处理耗时任务如网络请求,数据库的读取等。那么接下来让我们看看AsyncTask是怎么实现的吧。

首先来看看AsyncTask的使用:
public classMainActivity extends AppCompatActivity {public static finalStringTAG="MainActivity";@Overrideprotected voidonCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//任务串行执行new MyTask().execute("");//任务并行执行new MyTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECU  TOR,"");}  private static classMyTask extends AsyncTask {  //在执行任务之前调用(UIThread)@Overrideprotected voidonPreExecute() {super.onPreExecute();Log.e(TAG,"onPreExecute:"+Thread.currentThread().getName());}//在执行任务执行时调用(WorkThread)返回值传入onPostExecute@Overrideprotected String doInBackground(String... params) {//耗时操作代码try{for(inti =0;i <5;i++) {Thread.sleep(1000);onProgressUpdate(i*20);}}catch(InterruptedException e) {e.printStackTrace();}Log.e(TAG,"doInBackground:"+Thread.currentThread().getName() );return null;}//在执行任务执行百分比(WorkThread)@Overrideprotected voidonProgressUpdate(Integer... values) {super.onProgressUpdate(values);Log.e(TAG,"onProgressUpdate:"+Thread.currentThread().getName() );}//在执行任务执行完成调用(UIThread)@Overrideprotected voidonPostExecute(String s) {super.onPostExecute(s);Log.e(TAG,"onPostExecute:"+Thread.currentThread().getName());}}}
源码分析

AsyncTask如何工作?

首先来看execute()和executeOnExecutor()方法:
@MainThreadpublic final AsyncTask execute(Params... params) {    return executeOnExecutor(sDefaultExecutor, params);}

在这方法中会执行executeOnExecutor()这个方法,在这方法中又干了什么?

@MainThreadpublic 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()--> exec.execute(mFuture);
exec就是execute方法传入的也就是sDefaultExecutor这个线程池,那我们再来看看这个线程池的定义及实现:

private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;/*** An {@link Executor} that executes tasks one at a time in serial * order.  This serialization is global to a particular process.*/public static final Executor SERIAL_EXECUTOR = new   SerialExecutor();private static class SerialExecutor implements Executor { final ArrayDeque mTasks = new   ArrayDeque();    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);    }    }}

这个线程池也就是串行器的实现,我们来分析下它的实现:
首先是

final ArrayDeque mTasks = new ArrayDeque();

这是一个线性的双向队列,用于存储AsyncTask任务,当有新的任务时就是调用mTasks.offer()(此方法将指定的元素,在此deque队列的末尾);然后执行scheduleNext();在这方法中会执行队列中排列最前的任务THREAD_POOL_EXECUTOR.execute(mActive);
下面是THREAD_POOL_EXECUTOR的定义:

/** * 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核心数 +1;线程池最大容量为cpu核心数* 2 + 1;过剩的空闲线程的存活时间为1秒;待执行的任务队列初始容量:128个 。
通过上面的分析可以知道,不管是串行执行任务还是并行执行,其中的区别就是传入给executeOnExecutor()的线程池的不同,串行就是sDefaultExecutor,当然也可以指定自己定义的串行器,而并行则可以自己指定线程池来执行。

分析完任务的串行和并行的执行之后,接下来来看看doInBackground()是何时开始执行以及是如何将执行结果返回给onPostExecute()的:首先在AsyncTask的构造方法中定义了个WorkerRunnable implements Callable和一个FutureTask,不了解Callable和Future的可以看这里,我们看下构造方法中WorkerRunnable的实现
mWorker = new WorkerRunnable() {    public Result call() throws Exception {        mTaskInvoked.set(true);              Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);  //任务开始执行 Result result = doInBackground(mParams);   Binder.flushPendingCommands();        return postResult(result);    }};

通过上面代码可以发现执行后将结果交给postResult(result)方法处理,那我们在来看看这个方法的实现:

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

看到这个方法后就明白了,AsyncTask的原理就是封装了handler+Thread。

总结:

AsyncTask内部封装了Thread和Handler,调用AsyncTask的executeOnExecutor方法可以实现任务的并行执行也可以自定义线程池,调用execute方法可以实现任务的串行执行。

更多相关文章

  1. android对大图片压缩的方法
  2. android访问静态页面,出现405错误解决方法
  3. cocos2dx 玩转震动
  4. Android(安卓)开发
  5. Android事件分发机制的探索与发现之View篇
  6. android显示意图激活另一个Activity的方法
  7. ubuntu下android真机调试
  8. Android显示图片崩溃的解决办法
  9. Android(安卓)Fragment与Fragment、Activity通信的方式的总结

随机推荐

  1. 通过Android(安卓)studio将代码上传到git
  2. Android 第七天重置版_BroadCastReceiver
  3. Android xliff和字符串资源[Android开发
  4. Android 高性能编码一:多线程并发或分布式
  5. Android 中获取未安装APK的 图标 || icon
  6. Android framework学习
  7. android之Fragment(官网资料翻译)
  8. Android 利用广播实现黑名单【指定号码】
  9. android 获取string.xml中的value
  10. Android程序在genymotion模拟器上能够成