从源码分析AsyncTask

AsyncTask是Android提供的一个异步处理的方式。该方式使用较为方便,与Handler相比在代码上显得更简洁。
先来看看使用AsyncTask常用到的几个方法:
1.execute(Params… params),执行一个异步任务,需要我们在代码中调用此方法,触发异步任务的执行。(在UI线程调用

2.onPreExecute(),在execute(Params… params)被调用后立即执行,一般用来在执行后台任务前对UI做一些标记。

3.doInBackground(Params… params),在onPreExecute()完成后立即执行,用于执行较为费时的操作,此方法将接收输入参数和返回计算结果。在执行过程中可以调用publishProgress(Progress… values)来更新进度信息。

4.onProgressUpdate(Progress… values),在调用publishProgress(Progress… values)时,此方法被执行,直接将进度信息更新到UI组件上。

5.onPostExecute(Result result),当后台操作结束时,此方法将会被调用,计算结果将做为参数传递到此方法中,直接将结果显示到UI组件上。
详细的例子网上也很多了,此处不再列举,以上也是引用的别人的博客所述。
地址:http://blog.csdn.net/liuhe688/article/details/6532519
此篇主要是根据源码来分析AsyncTask的原理。

AsyncTask源码分析

老套路,先看看AsyncTask的构造函数。

/**
     * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
     */
    public AsyncTask() {
    //WorkerRunnable 为一个继承Callable<Result>接口的虚类
        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));
            }
        };

        mFuture = new FutureTask<Result>(mWorker) {//初始化mFuture 
            @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 occured while executing doInBackground()",
                            e.getCause());
                } catch (CancellationException e) {
                    postResultIfNotInvoked(null);
                }
            }
        };
    }

在构造函数中进行了一些初始化工作,并且最后都调用到了postResult,在postResultIfNotInvoked(get())中,其实最后也调用到了postResult。 这里用到了
Java并发编程:Callable、Future和FutureTask。有兴趣的可以看看。
在上面的代码中,当mWorker中定义的call方法被执行时,doInBackground就会开始执行,我们定义的后台任务也就真正开始了。实际上mFuture对象封装了call方法,当mFuture对象被提交到AsyncTask包含的线程池执行时,call方法就会被调用,我们定义的后台任务也就开始执行了。到此,我们先记住要使doInBackground()方法执行,就需要mFuture被执行,但是执行的地方还没找到。回想我们使用AsyncTask的时候,需要调用execute()方法,让程序跑起来。拿我们就先看看这个方法。

 &emp;我们建立一个继承于一个public abstract class AsyncTask

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

来看看executeOnExecutor方法 和sDefaultExecutor,params参数是一直传到doInBackground方法的。
sDefaultExecutor是什么呢?通过代码可以找到

public static final Executor SERIAL_EXECUTOR = Utils.hasHoneycomb() ? new SerialExecutor() :
            Executors.newSingleThreadExecutor(sThreadFactory);


private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

sDefaultExecutor 要不是一个 SerialExecutor要不就是一个单线程池。来看看SerialExecutor到底是什么。

private static class SerialExecutor implements Executor {

        //mTasks  缓存队列
        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);// 执行任务
            }
        }
    }

从上面的代码,可以看出首先由一个缓存队列mTasks ,该队列通过offer添加任务,通过THREAD_POOL_EXECUTOR.execute(mActive)去执行任务。那么接下来就是THREAD_POOL_EXECUTOR了。

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

很明显了THREAD_POOL_EXECUTOR就是一个线程池,并且规定了CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,TimeUnit.SECONDS等。从源码中也可以看到

    private static final int CORE_POOL_SIZE = 5;线程池大小5
    private static final int MAXIMUM_POOL_SIZE = 128;最大线程数128
    private static final int KEEP_ALIVE = 1;存活时间1s

接下来就是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();//该方法被调用,一般用来在执行后台任务前对UI做一些标记。

        mWorker.mParams = params;
        exec.execute(mFuture);

        return this;
    }

在代码的倒数第二行exec.execute(mFuture);这个方法。还记得之前mFuture对象么,这就是他被执行的地方了。从而doInBackground方法也就能够执行了,而且还由线程池进行控制。
以上为AsyncTask 调用流程的理解。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值