AsyncTask实现原理

轻量级异步类,是个抽象类

处理异步消息有很多方式,为何存在AsyncTask?

第一点,UI线程不能进行过多的耗时操作,容易引起ANR

第二点,只能在UI线程中去更新UI

第三点,AsyncTask封装了 Handler+Runnable,方便使用

代码实现

MyAsyncTask mTask = new MyAsyncTask();
mTask.execute();
class MyAsyncTask extends AsyncTask<String,Integer,String>{

    // 方法:doInBackground()
    // 作用:接收输入参数、执行任务中的耗时操作、返回 线程任务执行的结果
    @Override
    protected String doInBackground(String... strings) {
        try {
            int count = 0;
            int length = 1;
            while (count<99) {

                count += length;
                // 可调用publishProgress()显示进度, 之后将执行onProgressUpdate()
                publishProgress(count);
                // 模拟耗时任务
                Thread.sleep(50);
            }
        }catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }

    // 方法:onPostExecute()
    // 作用:接收线程任务执行结果、将执行结果显示到UI组件
    @Override
    protected void onPostExecute(String s) {
        // 执行完毕后,则更新UI
        mTextMessage.setText("加载完毕");
    }

    // 方法:onPreExecute()
    // 作用:执行 线程任务前的操作
    @Override
    protected void onPreExecute() {
        mTextMessage.setText("加载中");
    }

    // 方法:onProgressUpdate()
    // 作用:在主线程 显示线程任务执行的进度

    @Override
    protected void onProgressUpdate(Integer... progresses) {
        mProgressBar.setProgress(progresses[0]);//progressBar
        mTextMessage.setText("loading..." + progresses[0] + "%");
    }
}

实现原理

mTask.execute(); 从执行开始查看

// 类中参数为3种泛型类型
// 整体作用:控制AsyncTask子类执行线程任务时各个阶段的返回类型
// 具体说明:
    // a. Params:开始异步任务执行时传入的参数类型,对应excute()中传递的参数
    // b. Progress:异步任务执行过程中,返回下载进度值的类型
    // c. Result:异步任务执行完成后,返回的结果类型,与doInBackground()的返回值类型保持一致

public final AsyncTask<Params, Progress, Result> execute(Params... params) {
    return executeOnExecutor(sDefaultExecutor, params);
}

private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

public static final Executor SERIAL_EXECUTOR = new SerialExecutor();

sDefaultExecutor这个参数是干什么的?查找之后发现SerialExecutor线程池。再往下分析

public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
        Params... params) {
    if (mStatus != Status.PENDING) {//判断当前的AsyncTask是否正在运行,如果正在运行就抛出异常
        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(); //调用onPreExecute()执行初始化操作,说明该方法是最早运行的

    mWorker.mParams = params; //参数
    exec.execute(mFuture); //mFuture 这玩意又是什么东西
   
    return this;
}
public class FutureTask<V> implements RunnableFuture<V> {
public interface RunnableFuture<V> extends Runnable, Future<V> {

由此可知,是线程池里面执行了execute方法,参数实现了Runnable 接口

看看到底SerialExecutor线程池execute 方法干了什么

private static class SerialExecutor implements Executor {
    //双向队列
    final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
    Runnable mActive;
 // execute()被同步锁synchronized修饰
        // 即说明:通过锁使得该队列保证AsyncTask中的任务是串行执行的
        // 即 多个任务需1个个加到该队列中;然后 执行完队列头部的再执行下一个,以此类推 
public synchronized void execute(final Runnable r) {
        //将FutureTask的对象传入
        //向队列中加一个新的任务
        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);
        }
    }
}

 

private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();//获取cup核心数
private static final int CORE_POOL_SIZE = CPU_COUNT + 1; //设置线程池的核心数2-4,取决于cpu核心数
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;//设置线程池中线程数的最大值cpu*2 +1
private static final int KEEP_ALIVE = 1; //设置线程池线程保活状态

//初始化线程数量
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
    private final AtomicInteger mCount = new AtomicInteger(1);

    public Thread newThread(Runnable r) {
        return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
    }
};

//初始化任务队列为LinkedBlockingQueue 最大容量128
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
        = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
                TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);

由上面可知,做了一系列初始化状态

查看其构造方法

public AsyncTask() {
    //初始化WorkerRunnable变量 = 一个可存储参数的Callable对象
    mWorker = new WorkerRunnable<Params, Result>() {
        public Result call() throws Exception {
            //表示当前任务已经被执行了
            mTaskInvoked.set(true);
            //设置线程优先级
            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
            //noinspection unchecked
            //在这执行了doInBackground
            return postResult(doInBackground(mParams));
        }
    };
private Result postResult(Result result) {
    @SuppressWarnings("unchecked")
    //一看我擦,这不是Handler发送消息吗
    Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
            new AsyncTaskResult<Result>(this, result));
    //发送到标记的Handler
    message.sendToTarget();
    return result;
}

//看一下Handler收消息做了什么

private static class InternalHandler extends Handler {
    public InternalHandler() {
       //获取的是主线程,所以AsyncTask.execute()必须是在主线程操作
       //如果在子线程创建会怎么样( Only the original thread that created a view hierarchy can touch its views报出该异常)
        super(Looper.getMainLooper());
    }

    @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
    @Override
    public void handleMessage(Message msg) {
        AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
        switch (msg.what) {
            case MESSAGE_POST_RESULT:
            // 若收到的消息 = MESSAGE_POST_RESULT
            // 则通过finish() 将结果通过Handler传递到主线程
                // There is only one result
                result.mTask.finish(result.mData[0]);
                break;
            case MESSAGE_POST_PROGRESS:
                // 若收到的消息 = MESSAGE_POST_PROGRESS
                // 则回调onProgressUpdate()通知主线程更新进度的操作
                result.mTask.onProgressUpdate(result.mData);
                break;
        }
    }
}
  /**
  *  result.mTask.finish(result.mData[0])
  */
  private void finish(Result result) {
        // 先判断是否调用了Cancelled()
            // 1. 若调用了则执行我们复写的onCancelled()
            // 即 取消任务时的操作
            if (isCancelled()) {
                onCancelled(result);
            } else {

            // 2. 若无调用Cancelled(),则执行我们复写的onPostExecute(result)
            // 即更新UI操作
                onPostExecute(result);
            }
            // 注:不管AsyncTask是否被取消,都会将AsyncTask的状态变更为:FINISHED
            mStatus = Status.FINISHED;
        }
调用该方法会执行MESSAGE_POST_PROGRESS,返回回调onProgressUpdate
protected final void publishProgress(Progress... values) {
    if (!isCancelled()) {
        getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
                new AsyncTaskResult<Progress>(this, values)).sendToTarget();
    }
} 

总结:

首先本身会有个线程池提供,调用当前线程池的execute()并在AsyncTask构造开始在WorkerRunnable实例对象时复写的call()方法里,先调用 我们复写的doInBackground(mParams)执行耗时操作,然后调用postResult(result),通过InternalHandler 类 将任务消息传递到主线程;根据消息标识(MESSAGE_POST_RESULT)判断,最终通过finish()调用我们复写的onPostExecute(result),从而实现UI更新操作

AsyncTask 对象execute方法只能调用一次,如果想要调用需要重新new一个AsyncTask对象


 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

万子开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值