欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

AsyncTask源码分析

程序员文章站 2022-03-08 15:32:16
此文章从源码和方面分析AsyncTask,具体使用和内存泄漏不做分析,网上关于使用方法一搜一大堆,不在赘述。1、AsyncTask作为一个android中实现多线程常见的方法,定义如下:一个Android已封装好的轻量级异步类属于抽象类,即使用时需 实现子类2、话不多说,直接上源码public abstract class AsyncTask { private static final String LOG_TA....

此文章从源码和方面分析AsyncTask,具体使用和内存泄漏不做分析,网上关于使用方法一搜一大堆,不在赘述。

1、AsyncTask作为一个android中实现多线程常见的方法,定义如下:

  • 一个Android 已封装好的轻量级异步类
  • 属于抽象类,即使用时需 实现子类

2、话不多说,直接上源码

public abstract class AsyncTask<Params, Progress, Result> {
    private static final String LOG_TAG = "AsyncTask"
}

从这一句的定义可以看出,AsyncTask是一个抽象的封装类,使用的时候首先要继承。

 

下面是AsyncTask的构造方法,从下面可知,doInBackground运行在子线程,所以再此处处理耗时逻辑

/**
 * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
 *
 * @hide
 */
public AsyncTask(@Nullable Looper callbackLooper) {
    mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
        ? getMainHandler()
        : new Handler(callbackLooper);

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

负责发送消息,内部实际上是sendMessage操作

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

3、内部维护一个线程池ThreadPoolExecutor,代码如下

 */
public static final Executor THREAD_POOL_EXECUTOR;

static {
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
            CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
            sPoolWorkQueue, sThreadFactory);
    threadPoolExecutor.allowCoreThreadTimeOut(true);
    THREAD_POOL_EXECUTOR = threadPoolExecutor;
}

4、获取主线程looper,实现onProgressUpdate、onPostExecute、onCancelled操作,所以这三种回调回调是在主线程,可以直接进行UI操作

private static Handler getMainHandler() {
    synchronized (AsyncTask.class) {
        if (sHandler == null) {
            sHandler = new InternalHandler(Looper.getMainLooper());
        }
        return sHandler;
    }
}
private static class InternalHandler extends Handler {
    public InternalHandler(Looper looper) {
        super(looper);
    }

    @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   此处执行完成调用finish方法,finish中执行onPostExecute方法,也就是你可以在这个回调中更新UI
                result.mTask.finish(result.mData[0]);
                break;
            case MESSAGE_POST_PROGRESS:
                result.mTask.onProgressUpdate(result.mData);
                break;
        }
    }
}

 

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

5、execute方法必须运行在主线程

 

/**
 * Executes the task with the specified parameters. The task returns
 * itself (this) so that the caller can keep a reference to it.
 * 
 * <p>Note: this function schedules the task on a queue for a single background
 * thread or pool of threads depending on the platform version.  When first
 * introduced, AsyncTasks were executed serially on a single background thread.
 * Starting with {@link android.os.Build.VERSION_CODES#DONUT}, this was changed
 * to a pool of threads allowing multiple tasks to operate in parallel. Starting
 * {@link android.os.Build.VERSION_CODES#HONEYCOMB}, tasks are back to being
 * executed on a single thread to avoid common application errors caused
 * by parallel execution.  If you truly want parallel execution, you can use
 * the {@link #executeOnExecutor} version of this method
 * with {@link #THREAD_POOL_EXECUTOR}; however, see commentary there for warnings
 * on its use.
 *
 * <p>This method must be invoked on the UI thread.
 *
 * @param params The parameters of the task.
 *
 * @return This instance of AsyncTask.
 *
 * @throws IllegalStateException If {@link #getStatus()} returns either
 *         {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}.
 *
 * @see #executeOnExecutor(java.util.concurrent.Executor, Object[])
 * @see #execute(Runnable)
 */
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
    return executeOnExecutor(sDefaultExecutor, params);
}

onPreExecute方法在此处调用,也就是说onPreExecute也在UI线程执行

/**
 * Executes the task with the specified parameters. The task returns
 * itself (this) so that the caller can keep a reference to it.
 * 
 * <p>This method is typically used with {@link #THREAD_POOL_EXECUTOR} to
 * allow multiple tasks to run in parallel on a pool of threads managed by
 * AsyncTask, however you can also use your own {@link Executor} for custom
 * behavior.
 * 
 * <p><em>Warning:</em> Allowing multiple tasks to run in parallel from
 * a thread pool is generally <em>not</em> what one wants, because the order
 * of their operation is not defined.  For example, if these tasks are used
 * to modify any state in common (such as writing a file due to a button click),
 * there are no guarantees on the order of the modifications.
 * Without careful work it is possible in rare cases for the newer version
 * of the data to be over-written by an older one, leading to obscure data
 * loss and stability issues.  Such changes are best
 * executed in serial; to guarantee such work is serialized regardless of
 * platform version you can use this function with {@link #SERIAL_EXECUTOR}.
 *
 * <p>This method must be invoked on the UI thread.
 *
 * @param exec The executor to use.  {@link #THREAD_POOL_EXECUTOR} is available as a
 *              convenient process-wide thread pool for tasks that are loosely coupled.
 * @param params The parameters of the task.
 *
 * @return This instance of AsyncTask.
 *
 * @throws IllegalStateException If {@link #getStatus()} returns either
 *         {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}.
 *
 * @see #execute(Object[])
 */
@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;
}

上面标红的sDefaultExecutor实际上是一个静态内部类,实际上是另一个线程池,目的让执行多个线程任务按照顺序执行

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

mTask.poll是一个ArrayDeque,实现任务线程循环执行过程

好了大致就这些啦。

 

本文地址:https://blog.csdn.net/u011976443/article/details/114254312

相关标签: AsynTask 多线程