AsyncTask源码阅读

为什么要入坑?

1.新建AsyncTask的实例时重写的方法为什么有的在子线程执行,有的在主线程执行?
2.AsyncTask是怎么实现异步的呢?

1.执行入口

      AsyncTask task =  new AsyncTask() {
            @Override
            protected Object doInBackground(Object... params) {
                //执行中
                return null;
            }

            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                //执行前
            }

            @Override
            protected void onPostExecute(Object o) {
                super.onPostExecute(o);
                //执行后
            }
        };
 task.execute();

2.判断task的状态(状态不对就会抛出异常)

    @MainThread
    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方法确实在主线程中执行。
问:AsyncTask为什么只能执行一次?
答:从源码中可以看出,如果task是运行中的状态,则会抛出IllegalStateException的异常

3.在AsyncTask构造方法中创建mFuture实例(实质上是Runnable的实现类)

 public AsyncTask() {
       ...
       mFuture = new FutureTask(mWorker) {...}
      ...
}

public class FutureTask implements RunnableFuture {...}
public interface RunnableFuture extends Runnable, Future {
    void run();
}

在FutureTask会重写run方法,发现最终会调用c.call()方法

    public void run() {
        if (state != NEW ||
            !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
            return;
        try {
            Callable c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    //核心代码在这里
                    result = c.call();
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                if (ran)
                    set(result);
            }
        } finally {
            // runner must be non-null until state is settled to
            // prevent concurrent calls to run()
            runner = null;
            // state must be re-read after nulling runner to prevent
            // leaked interrupts
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }

call()方法哪里来的呢:

4.在AsyncTask构造方法中创建mWorker实例

   public AsyncTask() {
         ...
        mWorker = new WorkerRunnable() {
            //我在这呢!!!
            public Result call() throws Exception {
                mTaskInvoked.set(true);
                Result result = null;
                try {
                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                    //noinspection unchecked   回调方法在这里执行
                    result = doInBackground(mParams);
                    Binder.flushPendingCommands();
                } catch (Throwable tr) {
                    mCancelled.set(true);
                    throw tr;
                } finally {
                    //核心代码!!!最终会走这里
                    postResult(result);
                }
                return result;
            }
        };
      ...
}

从源码可以看出doInBackground会在FutureTask重写的run方法中执行,所以它是运行在子线程的。
其实FutureTask的实例会重写done方法,而他们最终也会走 postResult(result);

  mFuture = new FutureTask(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 occurred while executing doInBackground()",
                            e.getCause());
                } catch (CancellationException e) {
                    postResultIfNotInvoked(null);
                }
            }
        };
   private void postResultIfNotInvoked(Result result) {
        final boolean wasTaskInvoked = mTaskInvoked.get();
        if (!wasTaskInvoked) {
            postResult(result);
        }
    }

5.调用postResult方法(通过handler发送消息切换到主线程中)

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

6.通过handleMessage处理消息

    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:
                    //核心代码!!!最终会执行这里
                    result.mTask.finish(result.mData[0]);
                    break;
                case MESSAGE_POST_PROGRESS:
                    result.mTask.onProgressUpdate(result.mData);
                    break;
            }
        }
    }

通过Looper.getMainLooper();拿到了主线程的轮询器,现在已经回到主线程啦

7.最后会调用AsyncTask的finish方法

    private void finish(Result result) {
        if (isCancelled()) {
            onCancelled(result);
        } else {
            //回调方法在这里呢
            onPostExecute(result);
        }
        mStatus = Status.FINISHED;
    }

通过上一步,已经回到了主线程,所以 onPostExecute(result);必然是在主线程中执行的

最后说一句

本文只是对源码的简单查看,仍然有很多不解和疑惑。此文仅作为一个学习笔记

你可能感兴趣的:(AsyncTask源码阅读)