AsyncTask 工作原理(下)

来源:互联网 发布:照片文字软件下载 编辑:程序博客网 时间:2024/06/04 18:30

本文主要是根据AsyncTask 源码进一步对 AsyncTask 异步任务有更深入的理解
首先看一下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);                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;            }        };        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 occurred while executing doInBackground()",                            e.getCause());                } catch (CancellationException e) {                    postResultIfNotInvoked(null);                }            }        };    }

对于AsyncTask 构造函数 官网解释,创建一个异步任务,该构造函数必须在UI线程中调用。
在该构造函数内部,可以看到内部new出了两个新的对象分别是WorkerRunnable、FutureTask
对于WorkerRunnable该对象分析其源码是AsyncTask的一个内部类:

 private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {        Params[] mParams;    }

WorkerRunnable是一个抽象类,该类实现了Callable接口。
对于Callable接口:

public interface Callable<V> {    /**     * Computes a result, or throws an exception if unable to do so.     *     * @return computed result     * @throws Exception if unable to compute a result     */    V call() throws Exception;}

其官网内部解释:A task that returns a result and may throw an exception.
The Callable interface is similar to java.lang.Runnable , in that both are designed for classes whose instances are potentially executed by another thread. A Runnable , however, does not return a result and cannot throw a checked exception.
可以看出该接口其实跟Runnable接口类似,目的是作用于异步线程,而 Runnable 接口是无法返回一个result。所以定义了Callable接口。

返回AsyncTask 构造函数中实现的WorkRunnable抽象类,内部实现了 call()方法,在该方法内部可以看到

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

其主要目的是返回一个Result对象,对于该Result官网解释:
the type of the result of the background computation
通过异步任务返回的结果的类型。
在AsyncTask的基础使用中都了解 该Result 是通过外部设定的。
当然在call() 方法内部看到了result = doInBackground(mParams)、postResult(result)这两个比较熟悉的方法

在构造函数中的下一个实现对象是 FutureTask,其源码:

        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 occurred while executing doInBackground()",                            e.getCause());                } catch (CancellationException e) {                    postResultIfNotInvoked(null);                }            }        };

而对于FutureTask 在FutureTask.java 中

 public FutureTask(Callable<V> callable) {        if (callable == null)            throw new NullPointerException();        this.callable = callable;        this.state = NEW;       // ensure visibility of callable    }

其官网的解释:Creates a FutureTask that will, upon running, execute the given

对于AsyncTask的构造函数暂时讲到这里,对于FutureTask、WorkerRunnable等不是很清楚的暂时略过。

接下来根据AsyncTask的整个执行流程 来对AsyncTask做更进一步的了解。
对于AsyncTask 异步任务的执行内部有三种方法;

 @MainThread    public final AsyncTask<Params, Progress, Result> execute(Params... params) {        return executeOnExecutor(sDefaultExecutor, params);    }
  @MainThread    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;    }
 @MainThread    public static void execute(Runnable runnable) {        sDefaultExecutor.execute(runnable);    }

对于上述三个方法可以看到源码注释全部是在MainThread线程中执行。而对于方法一、方法二可以看出实质是执行了同一块代码:

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;

可以看到内部先对当前任务的Status进行判断,对于Status状态通过源码可以看到默认是:

 private volatile Status mStatus = Status.PENDING;

当将要执行的当前该任务是RUNNING、FINISHED 这两种状态,那么将会抛出异常。
当开始执行该Task时,Status状态设置为 RUNNING ,之后将会执行 onPreExecute()方法,通过源码分析可以看到onPreExecute()该方法是在主线程中执行的。其内部源码可以看到是一个空实现:

 @MainThread    protected void onPreExecute() {    }

因此外部可以通过重写该方法,在异步任务执行之前初始化一些基础数据。但由于该方法是运行在主线程中,切勿进行一些耗时操作

接下来执行了以下两行代码:

mWorker.mParams = params;exec.execute(mFuture);

首先是将 params参数赋值给全局变量mWorker中的一个变量,同时exec执行 execute操作。

下面具体分析该行代码:

exec.execute(mFuture)

通过参数(Executor exec) 可以看出exec实质上是一个线程池。对于线程池的了解读者可以参阅该文章
http://blog.csdn.net/liuluchao0543/article/details/52783025

而对于线程池execute() 方法的参数通过源码:

public interface Executor {    /**     * Executes the given command at some time in the future.  The command     * may execute in a new thread, in a pooled thread, or in the calling     * thread, at the discretion of the {@code Executor} implementation.     *     * @param command the runnable task     * @throws RejectedExecutionException if this task cannot be     * accepted for execution     * @throws NullPointerException if command is null     */    void execute(Runnable command);}

这里在进一步分析一下 FutureTask该类:

public class FutureTask<V> implements RunnableFuture<V> {}public interface RunnableFuture<V> extends Runnable, Future<V> {    /**     * Sets this Future to the result of its computation     * unless it has been cancelled.     */    void run();}

可以看到FutureTask本质是Runnable、Future的实现类。而对于线程池中的执行主要是看FutureTask中的run()方法:

 public void run() {        if (state != NEW ||            !U.compareAndSwapObject(this, RUNNER, 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);        }    }

可以看到在run()方法内主要调用来

callable.call()

而对于call()方法的具体实现是在AsyncTask 构造函数 中WorkRunnable实现对象中,
其内部源码:

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(mParams)该方法

 @WorkerThread    protected abstract Result doInBackground(Params... params);

而该方法可以看到不是在主线程主要用来做一些异步下载等耗时操作,具体的实现是通过客户度来实现。最后finish中执行了
postResult(result)方法

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

该postResult()方法可以看到内部实质上是通过Handler获取到Message消息,然后将该消息发送出去。
很明显当该消息发送出去之后,Handler会通过handlerMessage()方法接受到该消息,然后对该消息进行处理。
可以看到AsyncTask内部消息处理源码:

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]);                    break;                case MESSAGE_POST_PROGRESS:                    result.mTask.onProgressUpdate(result.mData);                    break;            }        }    }

可以看到接收到消息之后 执行该行代码:

result.mTask.finish(result.mData[0]);

具体源码:

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

对于isCancelled()方法对判断:

  public final boolean isCancelled() {        return mCancelled.get();    }  public final boolean get() {        return value != 0;    }

可以看到当不做任何设置时isCancelled()方法返回值为false;
从而在finish() 方法中执行onPostExecute(result)方法,该方法在AsyncTask中同样是一个空实现:

@MainThread    protected void onPostExecute(Result result) {    }

可以看出onPostExecute()该方法也是在主线程中执行,外部通过实现该方法可以用来更新UI

而对于 FutureTask中另一段代码:

if (ran)    set(result);
protected void set(V v) {        if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {            outcome = v;            U.putOrderedInt(this, STATE, NORMAL); // final state            finishCompletion();        }    }

可以看到set方法内部进行判断,如果该判断成立那么将会执行finishCompletion()方法

private void finishCompletion() {        // assert state > COMPLETING;        for (WaitNode q; (q = waiters) != null;) {            if (U.compareAndSwapObject(this, WAITERS, q, null)) {                for (;;) {                    Thread t = q.thread;                    if (t != null) {                        q.thread = null;                        LockSupport.unpark(t);                    }                    WaitNode next = q.next;                    if (next == null)                        break;                    q.next = null; // unlink to help gc                    q = next;                }                break;            }        }        done();        callable = null;        // to reduce footprint    }

可以看到内部会执行FutureTask的done()方法,而该方法的具体实现是在AsyTask构造函数中:

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

由此可以看到当线程池执行execute()方法之后,最终的调用会到AsyTask构造函数中FutureTask的实现类的done() 方法内部,在该方法内部可以看到主要是执行了该方法:

postResultIfNotInvoked(get())
 private void postResultIfNotInvoked(Result result) {        final boolean wasTaskInvoked = mTaskInvoked.get();        if (!wasTaskInvoked) {            postResult(result);        }    }

下面来具体分析一下postResultIfNotInvoked()方法内的执行,首先获取wasTaskInvoked值,

private volatile int value;public final boolean get() {        return value != 0;    }

通过上述方法可以看到wasTaskInvoked == false;则执行postResult(result) 方法

可以看到最终执行结果同样是执行到postResult()方法。

到这里整个AsyncTask的执行流程已经分析完成。

补充点:
对于AsyncTask内部实质存在两个线程池:

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(                CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,                sPoolWorkQueue, sThreadFactory);

1、THREAD_POOL_EXECUTOR, 异步线程池
参数说明:
1.corePoolSize=CPU核心数+1;
2.maximumPoolSize=2倍的CPU核心数+1;
3.核心线程无超时机制,非核心线程在闲置时间的超时时间为1s;
4.任务队列的容量为128。

而对于常用的execture() 方法实质是直接使用了AsyncTask内部默认的线程池 SERIAL_EXECUTOR:

2、SERIAL_EXECUTOR,同步线程池
SERIAL_EXECUTOR在THREAD_POOL_EXECUTOR的基础上添加了一个mTasks的集合来保证任务顺序执行(异步)

public static final Executor SERIAL_EXECUTOR = new SerialExecutor();private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
 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);            }        }    }

补充点二:

    /**     * 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     */    @WorkerThread    protected final void publishProgress(Progress... values) {        if (!isCancelled()) {            getHandler().obtainMessage(MESSAGE_POST_PROGRESS,                    new AsyncTaskResult<Progress>(this, values)).sendToTarget();        }    }

可以看出该方法可以在doInBackground()方法中被调用,当该方法被调用时可以传入当前下载进度等数据,在该方法内部可以看到同样是通过Handler方式发送了消息出去。
在Handler接受到该消息之后可以看到:

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

执行了onProgressUpdate ()方法,该方法是一个空实现可以用于更新当前页面到加载进度等。

 /**     * Runs on the UI thread after {@link #publishProgress} is invoked.     * The specified values are the values passed to {@link #publishProgress}.     *     * @param values The values indicating progress.     *     * @see #publishProgress     * @see #doInBackground     */    @SuppressWarnings({"UnusedDeclaration"})    @MainThread    protected void onProgressUpdate(Progress... values) {    }

到这里AsyncTask源码的解析已经解析完成,相信读者对AsyncTask异步任务有一定对了解了。

0 0
原创粉丝点击