Android 第三十周

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_21586317/article/details/82080401

谈谈对 AsyncTask 的理解

一、AsyncTask

AsyncTask 是一种轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行的进度和最终结果都传递给主线程并在主线程中更新 UI

总结:
1. AsyncTak 封装了 Thread 和 Handler,所以可以在子线程中执行任务,在主线程中更新 UI
2. 如果应用和主线程没有交互,则应该使用 Thread,而不是 AsyncTask

1.1 AsyncTask 的使用限制

1.AsyncTask 必须在主线程中加载,保证了 Handler 采用主线程的 Looper 构建
2.AsyncTask 的对象必须在主线程中创建,保证了 Handler 操作 UI 的线程是主线程
3. execute 方法必须在 线程 UI 调用,和上一条是一个意思
4. 一个 AsyncTask 对象只能调用一次 execute() 方法,否则会抛异常

二、AsyncTask 的工作原理

从 execute() 开始:

@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
    // 调用了 executeOnExecutor()
    return executeOnExecutor(sDefaultExecutor, params);
}

executeOnExecutor():

// AsyncTask 的初始状态 mStatus = PENDING
private volatile Status mStatus = Status.PENDING;

@MainThread
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) {
    // 当前状态不是 PENDING
    if (mStatus != Status.PENDING) {
        switch (mStatus) {
            // 不是 PENDING,是 RUNNING,提示 AsyncTask 正在执行,抛异常
            case RUNNING:
                throw new IllegalStateException("Cannot execute task:"
                        + " the task is already running.");
            // 不是 PENDING,是 FINISHED,提示 AsyncTask 对象只能执行一次,抛异常
            case FINISHED:
                throw new IllegalStateException("Cannot execute task:"
                        + " the task has already been executed "
                        + "(a task can be executed only once)");
        }
    }

    // 当前状态为 PENDING,设置为 RUNNING
    mStatus = Status.RUNNING;

    // AsyncTask 最先执行了 onPreExecute() 方法,在线程池执行任务前执行
    onPreExecute();

    mWorker.mParams = params;
    // 关键一:exec.execute(mFuture);
    exec.execute(mFuture);

    return this;
}

关键一:exec.execute(mFuture);

exec 是 execute() 中传入的 sDefaultExecutor

private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

public static final Executor SERIAL_EXECUTOR = new SerialExecutor();

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 指的是 mFuture,是一个 FutureTask 对象
                    r.run();
                } finally {
                    scheduleNext();
                }
            }
        });
        if (mActive == null) {
            scheduleNext();
        }
    }

    protected synchronized void scheduleNext() {
        if ((mActive = mTasks.poll()) != null) {
            THREAD_POOL_EXECUTOR.execute(mActive);
        }
    }
}

从上面的代码中,sDefaultExecutor 实际上是一个串行的线程池,AsyncTask 默认使用的就是该线程池,一个进程中所用的 AsyncTask 全部在这个线程池中排队执行

关键二:r.run();

r 指的是 mFuture,是一个 FutureTask 对象,是一个并发类,充当了 Runnable 的作用

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
                // AsyncTask 执行了 doInBackground() 方法
                result = doInBackground(mParams);
                Binder.flushPendingCommands();
            } catch (Throwable tr) {
                mCancelled.set(true);
                throw tr;
            } finally {
                // 关键三:postResult(result)
                postResult(result);
            }
            return result;
        }
    };

    // 创建 FutureTask 对象,传入了上面自定义的 WorkerRunnable 对象
    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);
            }
        }
    };
}

// 自定义的 WorkerRunnable 实现了 Callable 接口
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
    Params[] mParams;
}

r.run() -> FutureTask#run() -> callable#call() -> WorkerRunnable#call()
callback 就是通过 FutureTask 构造方法传入的自定义 WorkerRunnable,其实现了 Callable 接口,所以最终调用的是 WorkerRunnable#call(),执行流程如图所示:
FutureTask#run() 图解
由上图可知,WorkerRunnable#call() 最终将执行结果 result 传递给了 postResult() 方法

关键三:postResult(result);

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

发送的 MESSAGE_POST_RESULT 消息通过 AsyncTask 中自定义的静态内部类 InternalHandler 处理

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
                // 关键四:查看 AsyncTaskResult 定义
                result.mTask.finish(result.mData[0]);
                break;
            case MESSAGE_POST_PROGRESS:
                result.mTask.onProgressUpdate(result.mData);
                break;
        }
    }
}

result 是 AsyncTaskResult 对象

关键四:result.mTask.finish(result.mData[0])

@SuppressWarnings({"RawUseOfParameterizedType"})
private static class AsyncTaskResult<Data> {
    final AsyncTask mTask;
    final Data[] mData;

    AsyncTaskResult(AsyncTask task, Data... data) {
        mTask = task;
        mData = data;
    }
}

result.mTask.finish(result.mData[0]) 最终其实调用的是 AsyncTask#finish() 方法

private void finish(Result result) {
    // 任务已被取消
    if (isCancelled()) {
        // 调用 onCancelled() 方法
        onCancelled(result);
    } else {// 任务没有取消
        // 调用 onPostExecute() 方法
        onPostExecute(result);
    }
    mStatus = Status.FINISHED;
}

三、AsyncTask 版本演进

在 Android 1.6 之前,AsyncTask 是串行执行任务
在 Android 1.6 之后,3.0 之前,AsyncTask 采用线程池并行执行任务
从 Android 3.0 开始,为了避免并发带来的错误,AsyncTask 又采用一个线程来串行执行任务,但是提供了 executeOnExecutor(Executor exec, Params… params) 来并行执行任务

猜你喜欢

转载自blog.csdn.net/qq_21586317/article/details/82080401