AsyncTask 源码阅读笔记

* <p>AsyncTask is designed to be a helper class around {@link Thread} and {@link Handler}
* and does not constitute a generic threading framework. AsyncTasks should ideally be
* used for short operations (a few seconds at the most.) If you need to keep threads
* running for long periods of time, it is highly recommended you use the various APIs
* provided by the <code>java.util.concurrent</code> package such as {@link Executor},
* {@link ThreadPoolExecutor} and {@link FutureTask}.</p>

AsyncTask 应该被用来处理短时间(几秒)的操作。如果想要让线程长时间的运行,强烈推荐使用 java.util.concurrent 包下面的工具。

  

 

* <p>AsyncTask must be subclassed to be used. The subclass will override at least
* one method ({@link #doInBackground}), and most often will override a
* second one ({@link #onPostExecute}.)</p>

AsyncTask 是抽象类,子类需要实现其抽象方法,实例化后才能使用,下面是一个使用例子:
* <p>Here is an example of subclassing:</p>
* <pre class="prettyprint">
* private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
*     protected Long doInBackground(URL... urls) {
*         int count = urls.length;
*         long totalSize = 0;
*         for (int i = 0; i < count; i++) {
*             totalSize += Downloader.downloadFile(urls[i]);
*             publishProgress((int) ((i / (float) count) * 100));
*             // Escape early if cancel() is called
*             if (isCancelled()) break;
*         }
*         return totalSize;
*     }
*
*     protected void onProgressUpdate(Integer... progress) {
*         setProgressPercent(progress[0]);
*     }
*
*     protected void onPostExecute(Long result) {
*         showDialog("Downloaded " + result + " bytes");
*     }
* }

  


* <h2>AsyncTask's generic types</h2>
* <p>The three types used by an asynchronous task are the following:</p>
* <ol>
*     <li><code>Params</code>, the type of the parameters sent to the task upon
*     execution.</li>
*     <li><code>Progress</code>, the type of the progress units published during
*     the background computation.</li>
*     <li><code>Result</code>, the type of the result of the background
*     computation.</li>
* </ol>
* <p>Not all types are always used by an asynchronous task. To mark a type as unused,
* simply use the type {@link Void}:</p>
* <pre>
* private class MyTask extends AsyncTask<Void, Void, Void> { ... }
* </pre>

AsyncTask 的三个泛型参数:
Params --- Task 执行时需要的参数类型
Progress --- Task 执行时的进行类型
Result --- Task 执行完成之后返回的结果类型

  


* <h2>The 4 steps</h2>
* <p>When an asynchronous task is executed, the task goes through 4 steps:</p>
* <ol>
*     <li>{@link #onPreExecute()}, invoked on the UI thread before the task
*     is executed. This step is normally used to setup the task, for instance by
*     showing a progress bar in the user interface.</li>
*     <li>{@link #doInBackground}, invoked on the background thread
*     immediately after {@link #onPreExecute()} finishes executing. This step is used
*     to perform background computation that can take a long time. The parameters
*     of the asynchronous task are passed to this step. The result of the computation must
*     be returned by this step and will be passed back to the last step. This step
*     can also use {@link #publishProgress} to publish one or more units
*     of progress. These values are published on the UI thread, in the
*     {@link #onProgressUpdate} step.</li>
*     <li>{@link #onProgressUpdate}, invoked on the UI thread after a
*     call to {@link #publishProgress}. The timing of the execution is
*     undefined. This method is used to display any form of progress in the user
*     interface while the background computation is still executing. For instance,
*     it can be used to animate a progress bar or show logs in a text field.</li>
*     <li>{@link #onPostExecute}, invoked on the UI thread after the background
*     computation finishes. The result of the background computation is passed to
*     this step as a parameter.</li>
* </ol>

AsyncTask 执行的时候,下面四个方法将会顺序执行:
onPreExecute() 在主线程执行,在Task执行前调用。
doInBackground() 在后台线程执行,onPreExecute() 执行完之后,该方法立即执行。
onProgressUpdate() 在主线程执行,可用来展示 Task 的进度。
onPostExecute() 在主线程执行,Task 执行完之后,该方法执行。

  


* <h2>Cancelling a task</h2>
* <p>A task can be cancelled at any time by invoking {@link #cancel(boolean)}. Invoking
* this method will cause subsequent calls to {@link #isCancelled()} to return true.
* After invoking this method, {@link #onCancelled(Object)}, instead of
* {@link #onPostExecute(Object)} will be invoked after {@link #doInBackground(Object[])}
* returns. To ensure that a task is cancelled as quickly as possible, you should always
* check the return value of {@link #isCancelled()} periodically from
* {@link #doInBackground(Object[])}, if possible (inside a loop for instance.)</p>

取消任务,调用 cancel() 方法,调用该方法之后 isCancel() 方法会返回 true。
并且,onPostExecute() 方法不会执行,onCancelled() 会执行。
为了保证 Task 尽快取消,你应该在 doInBackground() 中随时检查 isCancelled() 的返回值。

  

AsyncTask 的构造函数

    /**
     * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
     */
    public AsyncTask() {
        mWorker = new WorkerRunnable<Params, Result>() {
            public Result call() throws Exception {
                mTaskInvoked.set(true);

                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                //noinspection unchecked
                return postResult(doInBackground(mParams));
            }
        };

        mFuture = new FutureTask<Result>(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 occured while executing doInBackground()",
                            e.getCause());
                } catch (CancellationException e) {
                    postResultIfNotInvoked(null);
                }
            }
        };
    }

在构造函数中,实例化了两个变量

mWorker 就是一个 Callable 的实现类。

mFuture 需要看一下 FutureTask 的源码。

 

下面看最主要的方法:

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

该方法调用了下面的方法:

    public final AsyncTask<Params, Progress, Result> 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;
    }

executeOnExecutor 方法可以指定 Executor 来执行多线程服务。

当我们调用了 execute 方法的时候,从代码中可以看出 onPreExecute() 会先执行。

然后是 exec.execute(mFuture) 执行,由于 mFuture 也实现了 Runnable 对象,并且还实现了 Callable 对象。

即 mFuture 的 run() 方法被调用:

public void run() {
        if (state != NEW ||
            !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                         null, Thread.currentThread()))
            return;
        try {
            Callable<V> 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);
        }
    }

其中,调用了 callable 的 call() 方法。由构造函数可知,mWorker 的 call() 方法被调用。

即执行了 doInBackground() 方法。然后,run() 方法的最后,会调用到 mFuture 的 done() 方法(省略一连串的调用)。

即 finish() 方法被调用(省略一连串的调用)。

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

可以看出,onPostExecute() 会被调用.....


onProgressUpdate() 由下面的方法触发:
    /**
     * This method can be invoked from {@link #doInBackground} to
     * publish updates on the UI thread while the background computation is
     * still running. Each call to this method will trigger the execution of
     * {@link #onProgressUpdate} on the UI thread.
     *
     * {@link #onProgressUpdate} will not be called if the task has been
     * canceled.
     *
     * @param values The progress values to update the UI with.
     *
     * @see #onProgressUpdate
     * @see #doInBackground
     */
    protected final void publishProgress(Progress... values) {
        if (!isCancelled()) {
            sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
                    new AsyncTaskResult<Progress>(this, values)).sendToTarget();
        }
    }

  

PS:序列执行器

    private static class SerialExecutor implements Executor {
        final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
        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);
            }
        }
    }

  



posted @ 2016-04-29 11:46  力能扛鼎  阅读(163)  评论(0编辑  收藏  举报