AsyncTask源码解析

来源:互联网 发布:域名后缀biz 编辑:程序博客网 时间:2024/06/14 19:47

最近看了许多AsyncTask源码解析的文章,于是想要自己整理一下,顺着源码自己解析一遍,所以产生了这篇文章。
首先看看其的解释说明吧,点击到源码中,有那么一段说明:
AsyncTask enables proper and easy use of the UI thread. This class allows to
* perform background operations and publish results on the UI thread without
* having to manipulate threads and/or handlers.

其作用是方便我们使用更新UI线程,我们可以不用工作线程和handler就直接可以在后台操作(即线程处理),然后把结果反馈回UI线程。大大简化了代码。
下面给出简单的模板:

  AsyncTask asyncTask=new AsyncTask() {            @Override            protected Object doInBackground(Object[] params) {            //后台任务                return null;            }            @Override            protected void onPostExecute(Object o) {            //后台任务完成后,这个在UI线程                super.onPostExecute(o);            }            @Override            protected void onProgressUpdate(Object[] values) {            //任务完成百分比监听,也再UI线程                super.onProgressUpdate(values);            }        };        asyncTask.execute(params);    }

首先从execute方法开始吧。
看源码:

 * <p>This method must be invoked on the UI thread. @MainThread    public final AsyncTask<Params, Progress, Result> execute(Params... params) {        return executeOnExecutor(sDefaultExecutor, params);    }

我们看到,这个方法必须在主线程当中调用,他返回的值是通过调用executeOnExecutor这个类,我们继续跟进。

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

我们都知道,asyncTask中的excute()方法一次只能执行一个task,这是为什么呢,我们从这里可以看出来,asyncTask中有三个状态(PENDING,RUNNING,FINISHED),分别对应着task的准备,正在运行,完成的状态,如果一个任务不是准备阶段的,asyncTask便会抛出异常:

 case RUNNING:         throw new IllegalStateException("Cannot execute task:" + " the task is already running."); case FINISHED:         throw new IllegalStateException("Cannot execute task:"

Ok,我们继续往下面看,当执行方法excute后,asyncTask会让状态变为RUNNING状态,然后执行onPreExecute();方法,这个方法是个抽象类,我们可以在asyncTask初始化的事后重写来进行执行asyncTask的前的准备工作。
接下来:mWorker.mParams = params;,这个是什么呢,我们并不了解,所以再点进去我们看看是个什么东东把

 private final WorkerRunnable<Params, Result> mWorker;private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {        Params[] mParams;    }

唉,这是啥,根本看不懂,,那我们找找还有没有什么地方使用了这个:

mWorker = new WorkerRunnable<Params, Result>() {            public Result call() throws Exception {                mTaskInvoked.set(true);                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);                //noinspection unchecked                Result result = doInBackground(mParams);                Binder.flushPendingCommands();                return postResult(result);            }        };

发现在asyncTask的构造方法中初始化了这个东东,在这段代码中我们看到了我们熟悉的东西doInBackground方法,我们在点进到postResult方法中:

private Result postResult(Result result) {        @SuppressWarnings("unchecked")        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,                new AsyncTaskResult<Result>(this, result));        message.sendToTarget();        return result;    }

这个我们熟悉啊,不就是handler机制么,如果没看过的同学可以看看的我写的文章:
http://blog.csdn.net/qq_25991953/article/details/50684416
我们发现他获得了一个消息,然后传递给handler,那肯定在asyncTask中一定会有handler的,我们找找,发现了如下的handler:

private static Handler getHandler() {        synchronized (AsyncTask.class) {            if (sHandler == null) {                sHandler = new InternalHandler();            }            return sHandler;        }    }private static class InternalHandler extends Handler {        public InternalHandler() {            super(Looper.getMainLooper());        }        @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;            }        }    }

从中我们是不是也可看出来asyncTask其实归根结底只是帮我们封装了一下handler的操作,简便了写代码~
我们看到在handler处理了两条信息,从字面上的意思我们就可以看出来是完成的状态还有更新的状态的信息,当task后台任务完成以后,给handler传回一个消息,设置asyncTask状态为finished,如果处于更新的状态,则调用onProgressUpdate(result.mData),即我们在UI线程中重写的方法进行UI页面的更新

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

好的,到现在还是不知道workRunnable有什么卵用啊,那我们先留着,继续看构造方法里面还留了一句话呢:

exec.execute(mFuture);

点进去!
@MainThread
public static void execute(Runnable runnable) {
sDefaultExecutor.execute(runnable);
}

发现是一个sDefaultExecutor,从名称可以推断出他是一个类似于池的东东(想想线程池),我们看看他是怎么实例化的:

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);            }        }    } public static final Executor THREAD_POOL_EXECUTOR            = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,                    TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);

哦!从中可以看出,和AsyncTask的运行其实是在其中用队列来维护他的运行
在其中还拥有一个线程池进行线程的维护,每添加一个线程,则会加入到队列的队尾,同时由线程池管理线程的运行。
回头再看一下这个方法

 exec.execute(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);                }            }        };private void postResultIfNotInvoked(Result result) {        final boolean wasTaskInvoked = mTaskInvoked.get();        if (!wasTaskInvoked) {            postResult(result);        }    }

有了!我们看到这个初始化传入了workRunnable当做参数进行的,最终调用了我们刚刚才分析过的postResult方法。

写的有点乱,整理一下:
首先我们调用了excute方法的时候,我们间接调用了executeOnExecutor方法,在这个方法:

        mStatus = Status.RUNNING;        onPreExecute();        mWorker.mParams = params;        exec.execute(mFuture);

依次做了开始任务的准备操作onPreExecute,设置参数mWorker.mParams,
调用sDefaultExecutor(即ArrayQueue)
最终返回了自己的实例:return this;
在asynctask()中初始化了两个变量:mWorker,mFuture,在mFuture中调用了postResult方法进行handler消息的传输操作。
当handler接收到信息后调用onPostExecute方法更新UI界面,所有的操作就已经完成了。
关于publishProgress方法,我们看到也是类似的方法

 @WorkerThread    protected final void publishProgress(Progress... values) {        if (!isCancelled()) {            getHandler().obtainMessage(MESSAGE_POST_PROGRESS,                    new AsyncTaskResult<Progress>(this, values)).sendToTarget();        }    }

解析完成!

0 0
原创粉丝点击