返回介绍

3.2、核心方法

发布于 2024-12-23 22:31:12 字数 6952 浏览 0 评论 0 收藏 0

1、execute() 方法

private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();

 /** AsyncTask 类的 execute 方法**/
 public final AsyncTask<Params, Progress, Result> execute(Params... params) {
  //调用 executeOnExecutor 方法
  return executeOnExecutor(sDefaultExecutor, params);
}

当执行 execute 方法时,实际上是调用了 executeOnExecutor 方法。这里传递了两个参数,一个是 sDefaultExecutor,一个是 params。从上面的源码可以看出,sDefaultExecutor 其实是一个 SerialExecutor 对象,实现了串行线程队列。params 其实最终会赋给 doInBackground 方法去处理。

2、executeOnExecutor() 方法

//exec 执行 AsyncTask.execute() 方法时传递进来的参数 sDefaultExecutor,这个 sDefaultExecutor 其实就是 SerialExecutor 对象。默认是串行执行的
//若想变成并发执行 exec 可以传入 AsyncTask.THREAD_POOL_EXECUTOR。
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
      Params... params) {
    //如果一个任务已经进入执行的状态,再执行就会抛异常。这就决定了一个 AsyncTask 只能执行一次
    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)");
      }
    }
	//一旦 executeOnExecutor 调用了就标记为运行状态
    mStatus = Status.RUNNING;
	//实际是调用子类里面的 onPreExecute
    onPreExecute();
	//将处理的参数类型赋值给 mWorker
    mWorker.mParams = params;
    //execute 是调用 SERIAL_EXECUTOR 的 execute,mFuture 就是之前 AsyncTask 构造初始化赋值的 FutureTask。
    exec.execute(mFuture);
    return this;
  }

这里要说明一下,AsyncTask 的异步任务有三种状态

  • PENDING 待执行状态。当 AsyncTask 被创建时,就进入了 PENDING 状态。
  • RUNNING 运行状态。当调用 executeOnExecutor,就进入了 RUNNING 状态。
  • FINISHED 结束状态。当 AsyncTask 完成(用户 cancel() 或任务执行完毕) 时,就进入了 FINISHED 状态。

3、SerialExecutor 的 execute 方法

  private static class SerialExecutor implements Executor {
  	//循环数组实现的双向 Queue。大小是 2 的倍数,默认是 16。有队头队尾两个下标
    final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
    //当前正在运行的 runnable
    Runnable mActive;

    public synchronized void execute(final Runnable r) {
      //添加到双端队列里面去
      mTasks.offer(new Runnable() {
        public void run() {
          try {
          	//执行的是 mFuture 就是之前 AsyncTask 构造初始化赋值的 FutureTask 的 run() 方法
            r.run();
          } finally {
          	//无论执行结果如何都会取出下一个任务执行
            scheduleNext();
          }
        }
      });
      //如果没有活动的 runnable,从双端队列里面取出一个 runnable 放到线程池中运行
      //第一个请求任务过来的时候 mActive 是空的
      if (mActive == null) {
      	//取出下一个任务来执行
        scheduleNext();
      }
    }
	
    protected synchronized void scheduleNext() {
      //从双端队列中取出一个任务
      if ((mActive = mTasks.poll()) != null) {
      	//线程池执行取出来的任务,真正执行任务的
        THREAD_POOL_EXECUTOR.execute(mActive);
      }
    }
  }//java

exec.execute(mFuture) ​ 执行时,SerialExecutor 将 FutureTask 作为参数执行 execute 方法。在 execute 方法中,假设 FutureTask 插入进了两个以上的任务队列到 mTasks 中,第一次过来 mActive==null ​,通过 mTasks.poll() 取出一个任务丢给线程池运行,线程池执行 r.run,其实就是执行 FutureTask 的 run 方法,因为传递进来的 r 参数就是 mFuture。等到上一个线程执完 r.run() 完之后,这里是通过一个 try-finally 代码块,并在 finally 中调用了 scheduleNext() 方法,保证无论发生什么情况,scheduleNext() 都会取出下一个任务执行。

接着因为 mActive 不为空了,不会再执行``scheduleNext()`,由于存在一个循环队列,每个 Runnable 被执行的时候,都进入去队列,然后在执行完后出队,才会进入下一个 Runnable 的执行流程。由此可知道这是一个串行的执行过程,同一时刻只会有一个线程正在执行,其余的均处于等待状态。

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);//调用子类的 doInBackground
        Binder.flushPendingCommands();
        return postResult(result);//执行完后通过 postResult 结果传递出去
      }
    };

上文中提到调用 call() 的流程: SerialExecutor.execute() -> FutureTask.run() -> WorkerRunnable.call() ​如果回调了 call() 方法,就会调用了 doInBackground(mParams) 方法,这都是在子线程中执行的。执行完后,将结果通过 postResult(result) 发送出去。

4、AsyncTask 的 postResult 方法

  private Result postResult(Result result) {
    @SuppressWarnings("unchecked")
    //获取一个 handler,等到一个消息,将结果封装在 Message
    Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
        new AsyncTaskResult<Result>(this, result));//new AsyncTaskResult<Result>(this, result) 将得到的结果再做了一层封装
    //将消息发送到主线程,会回调 handleMessage() 方法
    message.sendToTarget();
    return result;
  }

因为 postResult(Result result) 还是在子线程中调用的,如果要发送给主线程,必须通过 Handler。源码中使用 sHandler 并带着 MESSAGE_POST_RESULT 和封装了任务执行结果的对象 AsyncTaskResult,然后 message.sendToTarget() 开始发消息。

  private static Handler getHandler() {
    synchronized (AsyncTask.class) {
      if (sHandler == null) {
      	//初始化一个 InternalHandler,用与将结果发送给主线程
        sHandler = new InternalHandler();
      }
      return sHandler;
    }
  }

并在 InternalHandler 的 handleMessage 中开始处理消息,InternalHandler 的源码如下所示:

   private static class InternalHandler extends Handler {
    public InternalHandler() {
      // 这个 handler 是关联到主线程的
      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 消息,就会去执行 finish() 方法, finish() 源码如下文所示:
private void finish(Result result) {  
  if (isCancelled()) {  
    onCancelled(result);  
  } else {  
    onPostExecute(result);  
  }  
  mStatus = Status.FINISHED;  
} 

如果任务已经取消了,调用 onCancelled 方法,如果没被取消,则调用 onPostExecute() 方法。

  • 如果 doInBackground(Void... params) 调用 publishProgress() 方法,实际就是发送一条 MESSAGE_POST_PROGRESS 消息,就会去执行 onProgressUpdate() 方法。 publishProgress() 的源码如下文所示:
  @WorkerThread
  protected final void publishProgress(Progress... values) {
    if (!isCancelled()) {
      getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
          new AsyncTaskResult<Progress>(this, values)).sendToTarget();
    }
  }

如果你还不够清晰,请看下面的这个流程图。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文