AsyncTask源码分析

在我们开发过程中,经常会用到异步操作来进行界面的更新,一般来说,在子线程更新UI线程有三种方式,具体可以看:https://blog.csdn.net/qq_29451649/article/details/79529441 但是我们在写一些复杂的操作时直接使用Handler会有点麻烦,下面我们学习一下AsyncTask的使用以及实现的原理吧。

首先看AsyncTask的定义,方法如下:

public abstract class AsyncTask<Params, Progress, Result> {...

可以看到AsyncTask是泛型类,它包含3个参数,其中Params是参数的类型,Progress后台任务执行的任务类型,Result是返回的结果类型。我们在创建 AsyncTask的时候后,要有以下四个核心的方法:

protected Object doInBackground(Object[] objects) {
            return null;
        }

        @Override
        protected void onPostExecute(Object o) {
            super.onPostExecute(o);
        }

        @Override
        protected void onProgressUpdate(Object[] values) {
            super.onProgressUpdate(values);
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

其中除了doInBackground方法是在子线程中运行的,其他的都是在主线程中执行的。onPreExecute方法做的是初始化的工作,在任务执行前执行。doInBackground方法在onPreExecute方法之后之行,主要用来进行耗时操作,在我们执行的过程中可以调用publishProgress方法,将我们执行的进度传到下一个方法onProgressUpdate中(例如我们下载的操作),onPreExecute是在doInBackground执行完毕时进行的操作,在这里我们可以进行一些UI的更新等。

好了,用法什么的就不再说了,我们来看一下它到底是怎么实现这样的线程切换以及doInBackground到底是怎么执行操作的吧:

private static final BlockingQueue<Runnable> sPoolWorkQueue =
        new LinkedBlockingQueue<Runnable>(128);

/**
 * An {@link Executor} that can be used to execute tasks in parallel.
 */
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;
}

可以看到,在这个类中新建了一个sPoolWorkQueue,这是一个由链表组成的阻塞队列。然后通过这个阻塞队列创建了一个线程池threadPoolExecutor。下面看一下其他的参数:

private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// We want at least 2 threads and at most 4 threads in the core pool,
// preferring to have 1 less than the CPU count to avoid saturating
// the CPU with background work
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE_SECONDS = 30;

可以看到通过CPU_COUNT返回可用处理器的Java虚拟机的数量然后构建一个线程池。下面看一下doInBackground的实现:

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

可以看到整合各WorkerRunnable实现的是会很少用到的Callable接口,在它的call方法中调用了doInBackground方法并获取到了Result。下面我们看一下AsyncTask的exexute的执行过程:

@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);//1

    return this;
}

我们看到先是调用了executeOnExecutor方法,然后判断一下它的状态,如果是在运行和完成都会抛出异常。否则将状态设置为运行中,并调用onPreExecute方法,之后调用上面注释1处的方法,

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

在上面我们说过,mWorker继承了Callable接口,这里的mFuture是一个FutureTask实现了Runnable和Callable两个接口,接着我们看postResultIfNotInvoked这个方法:

private void postResultIfNotInvoked(Result result) {
    final boolean wasTaskInvoked = mTaskInvoked.get();
    if (!wasTaskInvoked) {
        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方法中创建了新的Message对象,到这里大家是不是都明白了,通过gethHandler方法得到Handler并通过这个handler发送消息

mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
        ? getMainHandler()
        : new Handler(callbackLooper);
        
private Handler getHandler() {
    return mHandler;
}

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

可以看到这个Handler和获取到的Looper对象是MainLooper。可以看到完成时会调用finish方法:

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

现在可以看到在结束时调用了postExecute方法并将Result传了过去。好了,到这里大家就该明白这这整个执行过程了吧。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值