zoukankan      html  css  js  c++  java
  • 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);
                }
            }
        }
    

      



  • 相关阅读:
    BZOJ 3809 Gty的二逼妹子序列 莫队算法+分块
    BZOJ 3131 SDOI2013 淘金 数位dp
    BZOJ 4408 FJOI2016 神秘数 可持久化线段树
    [leetcode] Reverse Linked List
    走迷宫问题总结
    [leetcode] Max Area of Island
    [leetcode] All Paths From Source to Target
    [leetcode] Arithmetic Slices
    [leetcode] Move Zeroes
    [leetcode] Linked List Cycle
  • 原文地址:https://www.cnblogs.com/aprz512/p/5445781.html
Copyright © 2011-2022 走看看