AsyncTask源码浅析

AsyncTask是Android的异步类……恩,大家应该都知道,直接分析吧。开始之前如果对Android的Callable,Future不了解的话可以先看看这篇文章 Java并发编程:Callable、Future和FutureTask

首先看看简单的用法,我自定义了一个TestAsyncTask:

class TestAsyncTask extends AsyncTask<String, Integer, Long> {
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }
    @Override
    protected void onPostExecute(Long aLong) {
        super.onPostExecute(aLong);
    }
    @Override
    protected Long doInBackground(String... params) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }
}

这里简单说一下,这里用到了三个泛型,第一个代表我们执行的任务需要的参数,就是doInBackground里面的参数,第二个泛型是用来更新进度的时候使用的,第三个泛型用来指定返回类型。

用的时候呢new TestAsyncTask().execute("helloWorld");

那么就从new开始分析先看一下AsyncTask的构造函数:

 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
                Result result = doInBackground(mParams);
                Binder.flushPendingCommands();
                return postResult(result);
            }
        };

        //创建一个mFuture 
        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接口,并且把任务封装在了call方法里面,这个方法主要就是执行了doInBackground方法.
然后从、又创建了一个FutureTask对象,看过上面那个文章的应该知道FutureTask既可以当Runnable使用又可以当Future使用。new FutureTask<Result>(mWorker),这里的Result就是任务执行完之后的返回值的类型,其实FutureTask只是包装了一下mWorker,所以我们要执行的任务就是FutureTask类,主要任务就是执行doInbackground,并把执行结果交给Future

下面继续看execute(“helloWorld”)方法:

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

这个方法实际上是调用了executeOnExecutor方法,我们一会再看这个方法,先看一下传入这个方法的两个参数:sDefaultExecutor,和params

先看看sDefaultExecutor的定义:

private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;    public static final Executor SERIAL_EXECUTOR = new SerialExecutor();

sDefaultExecutor 就是SerialExecutor,再看看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.run();
                    } finally {
                        //当前任务执行结束,执行下一个任务
                        scheduleNext();
                    }
                }
            });
            //如果当前没有正在执行的任务,那么从队列中取出一个任务
            if (mActive == null) {
                scheduleNext();
            }
        }

        protected synchronized void scheduleNext() {
            //从队列中取出任务并执行。
            if ((mActive = mTasks.poll()) != null) {
                THREAD_POOL_EXECUTOR.execute(mActive);
            }
        }
    }

可以看出SerialExecutor 中有一个任务队列mTasks,每次执行SerialExecutorexecute方法都会将任务加入这个任务队列,如果当前没有任务在执行,那么久取出一个任务让THREAD_POOL_EXECUTOR执行。THREAD_POOL_EXECUTOR比较简单,

params比较简单,就是new TestAsyncTask().execute("helloWorld");的时候传入的“hello world”

 public static final Executor THREAD_POOL_EXECUTOR
            = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
                    TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);              

可以看出THREAD_POOL_EXECUTOR只是一个常量池。

这样SerialExecutor 的任务就清楚了,将消息放入消息队列,并一个一个地串行地取出并交给THREAD_POOL_EXECUTOR执行

下面接着分析executeOnExecutor,

 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()
        onPreExecute();

        //把需要的参数传给mWorker,也就是传给FutherTask即mFuture
        mWorker.mParams = params;
        //这里的exec就是我们在execute方法中传给executeOnExecutor的第一个参数也就是sDefaultExecutor
        exec.execute(mFuture);
        return this;
    }

这段代码首先判断任务是否正在执行或者已经执行完了,如果是,那就抛出异常,否则执行onPreExecute();然后把我们在外面调用execute("hello world")传入的参数hello world参数传入mWorker即要执行的任务,然后调用sDefaultExecutorexecute方法。之后就像上面介绍的sDefaultExecutor先把任务加入任务队列然后串行的执行任务,任务的主要内容就是执行doInBackground并把返回的Result传入postResult(result);

分析到这里,我们已经可以知道doInBackground就是在THREAD_POOL_EXECUTOR线程池的子线程中执行的。

最后再来看一下postResult(result).方法:

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

这里可以看到,就是把result放到message中并把getHandler得到的handler作为message的target,把message的what设置成MESSAGE_POST_RESULT表示这个消息代表任务执行的结果。看一下getHandler:

 private static Handler getHandler() {
        synchronized (AsyncTask.class) {
            if (sHandler == null) {
                sHandler = new InternalHandler();
            }
            return sHandler;
        }
    }

getHandler只是返回了一个InternalHandler

        //使用的是UI线程的Looper和消息队列
        public InternalHandler() {
            super(Looper.getMainLooper());
        }

        @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
        @Override
        public void handleMessage(Message msg) {
            AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
            switch (msg.what) {
                    //what是MESSAGE_POST_RESULT,那么就处理doInbackground返回的结果
                    case MESSAGE_POST_RESULT:
                    // There is only one result
                   // finish内部会调用我们实现的onPostExecute方法
                    result.mTask.finish(result.mData[0]);
                    break;
                    //what是MESSAGE_POST_PROGRESS,那么就调用onProgressUpdate来更新progress
                case MESSAGE_POST_PROGRESS:
                    result.mTask.onProgressUpdate(result.mData);
                    break;
            }
        }
    }

上面的注释写得很明白了,根据消息的不同,使用handler在UI线程中处理结果,或者更新progerss。
看看finish和的代码

 private void finish(Result result) {
        if (isCancelled()) {
            onCancelled(result);
        } else {
            //onPostExecute就是在这里执行的
            onPostExecute(result);
        }
        mStatus = Status.FINISHED;
    }
    protected final void publishProgress(Progress... values) {
        if (!isCancelled()) {
            //publishProgress把what为MESSAGE_POST_PROGRESS的消息发送给了
           // InternalHandler,所以更新了progress
            getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
                    new AsyncTaskResult<Progress>(this, values)).sendToTarget();
        }
    }

看到这里可以总结一下,doInBackground方法是在线程池中的线程中执行,而onPreExecute是在UI线程中执行,而onPostExecute和onProgressUpdate是用过InternalHandler 从而在UI线程执行的。而且一个AsyncTask对象执行结束之后也就没用了,一个AsyncTask对象只能execute一次,否则会报异常,如果还想执行一个任务需要重新创建一个AsyncTask对象,这一点可以从executeOnExecutor的代码看出来

到这里就算大致的分析完了,其实还有许多细节没有提到,感觉自己没有看源码光看别人的文章的话还是很难理解,最好没事的话多翻翻源码,AsyncTask这个类的源码都在一个文件里面也不多。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值