AsyncTask 源码详解

2017-10-13  本文已影响0人  刘佳阔
asynetask.png

1.常规写法

    //三个参数的意思分别是,线程执行的参数类型,线程异步执行进度的任务类型,返回值的类型
    private class MyAsync extends AsyncTask<Params, Progress, Result> {
    
    @Override
    protected Result doInBackground(Params... params) { //此方法在子线程执行,参数就是上文的Params类型
        publishProgress(6);  //这个方法可以把异步执行进度发布到主线程去,参数是 Progress类型
        return 6L;
    }

    @Override
    protected void onPostExecute(Result aLong) {//在异步线程完成后被调用,运行在主线程
        super.onPostExecute(aLong);
    }

     @Override
    protected void onCancelled() {//异步任务被取消时调用,他和onPostExecute 只能有一个被调用
        super.onCancelled();
    }

    @Override
    protected void onPreExecute() {//该方法在异步任务执行前调用,运行在主线程
        super.onPreExecute();
    }

    @Override
    protected void onProgressUpdate(Progress... values) { //publishProgress调用后,就把参数传到了这个方法里,运行在主线程,用来更新异步任务执行进度
        super.onProgressUpdate(values);
    }
}

然后在主线程中调用

 new MyAsync().execute("a"); //这句话必须在主线程中调用.对象的创建和execute的执行,都必须在主线程

2 源码讲解

1.先从成员变量看起

public static final Executor SERIAL_EXECUTOR = new SerialExecutor(); //一个继承自Executor的内部类,  注意是用来把线程添加进线程的任务集合
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

private static InternalHandler sHandler;//内部用来发送消息给主线程的Handler

private final WorkerRunnable<Params, Result> mWorker; //内部类,继承自Callable,用来返回线程的结果与Runnable 类似.只是Runnable 不能返回结果.
private final FutureTask<Result> mFuture; // FutureTask的子类,也是Runnable的子类,可以取消线程及获得线程的执行结果.

2.构造函数

public AsyncTask() {
    mWorker = new WorkerRunnable<Params, Result>() { //标识接受的参数类型和返回的参数类型
        public Result call() throws Exception {
            mTaskInvoked.set(true);
            Result result = null;
            try {
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);//设置优先级
                
                result = doInBackground(mParams);
        //可以看到.在mWorker的call方法被调用时,会执行暴露的doInBackground()方法,意味着call要在子线程
        执行,同事把结果保存在result中.这才是真正工作的地方.
                
            } catch (Throwable tr) {
                mCancelled.set(true);
                throw tr;
            } finally {
                postResult(result); //发送结果的方法.下边讲解
            }
            return result;
        }
    };
    //mFuture对象封装了mWorker的call方法,当mFuture对象被提交到AsyncTask包含的线程池执行时,call方法就会被调用
    mFuture = new FutureTask<Result>(mWorker) { 
        @Override
        protected void done() {
            try {
                postResultIfNotInvoked(get());//没有执行的话,也发送一个消息出去
            } catch (InterruptedException e) {
                android.util.Log.w(LOG_TAG, e);
            } catch (CancellationException e) {
                postResultIfNotInvoked(null);
            }
        }
    };
}
  1. execute 方法

    @MainThread  //标识了需要在主线程调用
     public final AsyncTask<Params, Progress, Result> execute(Params... params) {
         return executeOnExecutor(sDefaultExecutor, params); //sDefaultExecutor 是 SerialExecutor类的对象
     }
    
     @MainThread
     public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
         Params... params) {
    
     mStatus = Status.RUNNING; //更新状态
    
     onPreExecute();  //这是在异步线程执行前调用的方法,在主线程中,
    
     mWorker.mParams = params; //params 是我们输入的参数,mWorker会在call方法被调用是把参数传到doInBackground 方法中,间构造函数.
     exec.execute(mFuture);//exec 是sDefaultExecutor  
     return this;
     }
    
    1. sDefaultExecutor.exec
  private static class SerialExecutor implements Executor {
        final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();//以数组的形式储存所有要执行的后台任务
      Runnable mActive; //当前正执行的异步线程

      public synchronized void execute(final Runnable r) {//此时的 r是上文的 mFuture
          mTasks.offer(new Runnable() {//mTasks会把 runnable添加到数组的最后边,
              public void run() {
                  try {
                      r.run();  //可以看到,在执行万mRuture的方法后,还要同mTasks中取出下一任务,穿行执行
                  } finally {
                      scheduleNext();
                  }
              }
         });
         if (mActive == null) {//第一次尽量.肯定为null,然后就从mTasks中取出任务执行
              scheduleNext();
          }
      }
//从上边的方法可以看到.sDefaultExecutor 的作用仅仅是把线程添加到数组中,同时使线程可以穿行执行.
//而下边的方法可看出.真正执行线程运行的,是 THREAD_POOL_EXECUTOR 这个Executor
    protected synchronized void scheduleNext() {
        if ((mActive = mTasks.poll()) != null) {
            THREAD_POOL_EXECUTOR.execute(mActive);
        }
    }
}
  1. THREAD_POOL_EXECUTOR
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); //cpu核心数
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));//核心线程数2-4
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1; //最大线程数
private static final int KEEP_ALIVE_SECONDS = 30; //线程存活时间.

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;
}

6.Handler.

 在 5中执行了mFuture 的run方法后, 会调用 没Worker的call方法,在doInBackground之后,调用了
  postResult(result);方法.
  private Result postResult(Result result) {
    @SuppressWarnings("unchecked")
    Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
            new AsyncTaskResult<Result>(this, result)); 
  //getHandler 返回的是 sHandler 是一个Handler的实现类.
    message.sendToTarget();
    return result;
}

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]); //此时的result.mTask 就是我们new的 AsyneTask,这里是线程完成后的消息处理,下边是  调用 publishProgress 的消息处理.
                break;
            case MESSAGE_POST_PROGRESS:
                result.mTask.onProgressUpdate(result.mData);
                break;
        }
    }
}
 private void finish(Result result) {//在这里就是线程执行完成后的方法,可以看到,只能调用其中的一个.
    if (isCancelled()) {
        onCancelled(result);
    } else {
        onPostExecute(result);
    }
    mStatus = Status.FINISHED;
}

这里.就分析完成,最后大概记录一下.AsyncTask开始执行时,会把参数封装进 (WorkerRunnable) mWorker,然后mWorker 是被(FutureTask) mFuture所持有.执行时, (SerialExecutor) sDefaultExecutor把

(FutureTask) mFuture 进行封装后添加进线程集合(ArrayDeque<Runnable>) mTask并调用 (ThreadPoolExecutor) THREAD_POOL_EXECUTOR 的execute方法, 从 (ArrayDeque<Runnable>) mTask 开始执行线程,然后 (FutureTask) mFuture 被执行时,会调用 (WorkerRunnable) mWorker 的call方法,call方法又会调用AsyncTask 的 doInBackground()方法,真正在子线程开始执行, doInBackground的返回结果会通过内部的(InternalHandler) sHandler 发送并处理, (InternalHandler) sHandler 处理时会调用AsyncTask的finish 方法,finish方法要么执行onCancelled,要么执行onPostExecute.到此.异步执行完成

上一篇 下一篇

猜你喜欢

热点阅读