AsyncTask源码分析

前言

    AsyncTask是一种异步处理线程的类,他可以在后台处理一些耗时的操作,它相当于Thread线程和handler的合体,为我们更新UI,执行耗时操作,提供方便。

分析源码

https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/java/android/os/AsyncTask.java

    AsyncTask中有三个泛型变量,如下:

public abstract class AsyncTask<Params, Progress, Result> 

    继承自AsyncTask必须重写一个方法,doInBackground(),该方法传入参数是泛型变量Params,返回的是泛型变量Result。它工作在worker线程。

    AsyncTask的实例化:

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

        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处理相关的Handler,用于执行重写方法doInBackground的worker,用于将worker处理后返回数据送到UI处理的future。

    在执行doInBackground方法的时候,worker是一个新线程,该线程被设置为后台线程。

    我们外部使用的时候,是通过execute(…)来开始执行task.

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

    execute()中可以传递多个参数,也可以不传。首先会判断当前TASK的状态,如果当前task状态为运行或者完成状态,那么task都不会继续往下走。这样是为了保证一个task只会执行一次。

    task状态有三种,未运行,运行和结束运行。如下:

    public enum Status {
        /**
         * Indicates that the task has not been executed yet.
         */
        PENDING,
        /**
         * Indicates that the task is running.
         */
        RUNNING,
        /**
         * Indicates that {@link AsyncTask#onPostExecute} has finished.
         */
        FINISHED,
    }

    task必须在UI线程中运行,所以在执行execute方法时候,可以直接调用onPreExecute()方法,来进行前置UI的处理,比如开启进度条。

    接下来线程池会开启一个线程来执行初始化时候实例化的feature,feature是一个FutureTask,依据FutureTask的特性,worker只会执行一次,在worker执行完成之后,才会执行接下来的动作。

    worker线程不管是否可以正常执行,最后都在执行方法postResult(Result)将结果数据发送给handler,由主UI线程来执行方法onPostExecute(),并将task状态转为完成状态。

    FeatureTask重写了done()方法,从源码中看,done方法中执行了
postResultIfNotInvoked(get()),这个方法中判断worker是否正常执行.

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

    当发现worker线程没有正常启动执行,那么它会执行最后的方法onPostExecute()来保证流程全部走完。变量wasTaskInvoked在worker初始化的时候会被设为true,之后也没有设为false的选项,所以如果不出意外,是不会执行done()里边的方法的。

    task中还有一个方法cancel(),用来终止取消task的执行,查看源码可以看到task通过全局原子布尔变量来控制线程执行取消。

private final AtomicBoolean mCancelled = new AtomicBoolean();

    task取消的情况有:

  • worker线程执行出现异常,会强制取消终止task的运行
  • 用户手动调用cancel方法,此时,会设置该变量为true,同时featuretask也会执行取消执行worker的方法

    task取消之后,onPostExecute()方法将不会再执行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值