AsyncTask源码解析
Posted 夜宿山寺
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AsyncTask源码解析相关的知识,希望对你有一定的参考价值。
快要毕业了,最近在阿里巴巴校园招聘面试,一面过了,感觉挺轻松,可能是运气好,面试官感觉比我腼腆一些,我俩从android绕到了spring mvc 到数据库悲观锁 到linux 然后又会到了android。这个面试收获挺大,多线程方面还得加强一下,但好在的是跟面试官谈了半个多小时源码,可能这一点比较加分,继续准备二面。分析一些源码吧
public abstract class AsyncTask<Params, Progress, Result>
private static final String LOG_TAG = "AsyncTask";
//定义线程池的最小数量
private static final int CORE_POOL_SIZE = 5;
//定义线程池的最大数量
private static final int MAXIMUM_POOL_SIZE = 128;
//设置线程存活时间
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());
;
//定义一个线程工作队列,当超过十个线程的工作的时候会导致阻塞效果
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(10);
//主要使用来执行任务
public static final Executor THREAD_POOL_EXECUTOR
= new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
/**
* An @link Executor that executes tasks one at a time in serial
* order. This serialization is global to a particular process.
*/
//定义自己实现的一个Executor,在里面实现自己的一个ArrayDeque双端队列
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static final int MESSAGE_POST_RESULT = 0x1;
private static final int MESSAGE_POST_PROGRESS = 0x2;
//实现一个自己的handler
private static final InternalHandler sHandler = new InternalHandler();
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
//实现了Callable的一个抽象类,在里面封装
private final WorkerRunnable<Params, Result> mWorker;
//采用future模式执行任务
private final FutureTask<Result> mFuture;
private volatile Status mStatus = Status.PENDING;
private final AtomicBoolean mTaskInvoked = new AtomicBoolean();
private static class SerialExecutor implements Executor
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
//往队列里面提交runnable对象,然后调用scheduleNext去执行mActive , 开启一个线程,然后通过同步调用去执行一个runnable对象
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);
/**
* Indicates the current status of the task. Each status will be set only once
* during the lifetime of a task.
*/
public enum Status
/**
* Indicates that the task has not been executed yet.
*/
PENDING,
/**
* Indicates that the task is running.
*/
RUNNING,
/**
* Indicates that @link AsyncTask#onPostExecute has finished.
*/
FINISHED,
/** @hide Used to force static handler to be created. */
public static void init()
sHandler.getLooper();
//设置自己的一个Executor对象,否则就采用系统默认的
/** @hide */
public static void setDefaultExecutor(Executor exec)
sDefaultExecutor = exec;
//初始化一个AsyncTask对象
public AsyncTask()
//初始化一个Callable对象 实现call方法,并且设置mTaskInvoked为true 设置线程级别为后台线程
//然后去调用子类实现的doInBackground来完成耗时操作,完成之后在调用postResult来发送消息给自定义的hadnler
mWorker = new WorkerRunnable<Params, Result>()
public Result call() throws Exception
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
return postResult(doInBackground(mParams));
;
//实现自己的FutureTask done方法 当此任务转换到状态 isDone(不管是正常地还是通过取消)时,调用受保护的方法
mFuture = new FutureTask<Result>(mWorker)
@Override
protected void done()
try
final Result result = get();
postResultIfNotInvoked(result);
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);
catch (Throwable t)
throw new RuntimeException("An error occured while executing "
+ "doInBackground()", t);
;
private void postResultIfNotInvoked(Result result)
final boolean wasTaskInvoked = mTaskInvoked.get();
if (!wasTaskInvoked)
postResult(result);
//把result通过handler发送出去
private Result postResult(Result result)
Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
/**
* Returns the current status of this task.
*
* @return The current status.
*/
public final Status getStatus()
return mStatus;
/**
* Override this method to perform a computation on a background thread. The
* specified parameters are the parameters passed to @link #execute
* by the caller of this task.
*
* This method can call @link #publishProgress to publish updates
* on the UI thread.
*
* @param params The parameters of the task.
*
* @return A result, defined by the subclass of this task.
*
* @see #onPreExecute()
* @see #onPostExecute
* @see #publishProgress
*/
//执行后台任务的方法
protected abstract Result doInBackground(Params... params);
/**
* Runs on the UI thread before @link #doInBackground.
*
* @see #onPostExecute
* @see #doInBackground
*/
//在执行doInBackground之前调用的
protected void onPreExecute()
/**
* <p>Runs on the UI thread after @link #doInBackground. The
* specified result is the value returned by @link #doInBackground.</p>
*
* <p>This method won't be invoked if the task was cancelled.</p>
*
* @param result The result of the operation computed by @link #doInBackground.
*
* @see #onPreExecute
* @see #doInBackground
* @see #onCancelled(Object)
*/
@SuppressWarnings("UnusedDeclaration")
protected void onPostExecute(Result result)
/**
* Runs on the UI thread after @link #publishProgress is invoked.
* The specified values are the values passed to @link #publishProgress.
*
* @param values The values indicating progress.
*
* @see #publishProgress
* @see #doInBackground
*/
//进度刷新时候调用,在这里可以进行ui更新
@SuppressWarnings("UnusedDeclaration")
protected void onProgressUpdate(Progress... values)
/**
* <p>Runs on the UI thread after @link #cancel(boolean) is invoked and
* @link #doInBackground(Object[]) has finished.</p>
*
* <p>The default implementation simply invokes @link #onCancelled() and
* ignores the result. If you write your own implementation, do not call
* <code>super.onCancelled(result)</code>.</p>
*
* @param result The result, if any, computed in
* @link #doInBackground(Object[]), can be null
*
* @see #cancel(boolean)
* @see #isCancelled()
*/
@SuppressWarnings("UnusedParameters")
protected void onCancelled(Result result)
onCancelled();
/**
* <p>Applications should preferably override @link #onCancelled(Object).
* This method is invoked by the default implementation of
* @link #onCancelled(Object).</p>
*
* <p>Runs on the UI thread after @link #cancel(boolean) is invoked and
* @link #doInBackground(Object[]) has finished.</p>
*
* @see #onCancelled(Object)
* @see #cancel(boolean)
* @see #isCancelled()
*/
protected void onCancelled()
/**
* Returns <tt>true</tt> if this task was cancelled before it completed
* normally. If you are calling @link #cancel(boolean) on the task,
* the value returned by this method should be checked periodically from
* @link #doInBackground(Object[]) to end the task as soon as possible.
*
* @return <tt>true</tt> if task was cancelled before it completed
*
* @see #cancel(boolean)
*/
public final boolean isCancelled()
return mFuture.isCancelled();
/**
* <p>Attempts to cancel execution of this task. This attempt will
* fail if the task has already completed, already been cancelled,
* or could not be cancelled for some other reason. If successful,
* and this task has not started when <tt>cancel</tt> is called,
* this task should never run. If the task has already started,
* then the <tt>mayInterruptIfRunning</tt> parameter determines
* whether the thread executing this task should be interrupted in
* an attempt to stop the task.</p>
*
* <p>Calling this method will result in @link #onCancelled(Object) being
* invoked on the UI thread after @link #doInBackground(Object[])
* returns. Calling this method guarantees that @link #onPostExecute(Object)
* is never invoked. After invoking this method, you should check the
* value returned by @link #isCancelled() periodically from
* @link #doInBackground(Object[]) to finish the task as early as
* possible.</p>
*
* @param mayInterruptIfRunning <tt>true</tt> if the thread executing this
* task should be interrupted; otherwise, in-progress tasks are allowed
* to complete.
*
* @return <tt>false</tt> if the task could not be cancelled,
* typically because it has already completed normally;
* <tt>true</tt> otherwise
*
* @see #isCancelled()
* @see #onCancelled(Object)
*/
public final boolean cancel(boolean mayInterruptIfRunning)
return mFuture.cancel(mayInterruptIfRunning);
/**
* Waits if necessary for the computation to complete, and then
* retrieves its result.
*
* @return The computed result.
*
* @throws CancellationException If the computation was cancelled.
* @throws ExecutionException If the computation threw an exception.
* @throws InterruptedException If the current thread was interrupted
* while waiting.
*/
public final Result get() throws InterruptedException, ExecutionException
return mFuture.get();
/**
* Waits if necessary for at most the given time for the computation
* to complete, and then retrieves its result.
*
* @param timeout Time to wait before cancelling the operation.
* @param unit The time unit for the timeout.
*
* @return The computed result.
*
* @throws CancellationException If the computation was cancelled.
* @throws ExecutionException If the computation threw an exception.
* @throws InterruptedException If the current thread was interrupted
* while waiting.
* @throws TimeoutException If the wait timed out.
*/
public final Result get(long timeout, TimeUnit unit) throws InterruptedException,
ExecutionException, TimeoutException
return mFuture.get(timeout, unit);
/**
* Executes the task with the specified parameters. The task returns
* itself (this) so that the caller can keep a reference to it.
*
* <p>Note: this function schedules the task on a queue for a single background
* thread or pool of threads depending on the platform version. When first
* introduced, AsyncTasks were executed serially on a single background thread.
* Starting with @link android.os.Build.VERSION_CODES#DONUT, this was changed
* to a pool of threads allowing multiple tasks to operate in parallel. After
* @link android.os.Build.VERSION_CODES#HONEYCOMB, it is planned to change this
* back to a single thread to avoid common application errors caused
* by parallel execution. If you truly want parallel execution, you can use
* the @link #executeOnExecutor version of this method
* with @link #THREAD_POOL_EXECUTOR; however, see commentary there for warnings on
* its use.
*
* <p>This method must be invoked on the UI thread.
*
* @param params The parameters of the task.
*
* @return This instance of AsyncTask.
*
* @throws IllegalStateException If @link #getStatus() returns either
* @link AsyncTask.Status#RUNNING or @link AsyncTask.Status#FINISHED.
*/
public final AsyncTask<Params, Progress, Result> execute(Params... params)
return executeOnExecutor(sDefaultExecutor, params);
/**
* Executes the task with the specified parameters. The task returns
* itself (this) so that the caller can keep a reference to it.
*
* <p>This method is typically used with @link #THREAD_POOL_EXECUTOR to
* allow multiple tasks to run in parallel on a pool of threads managed by
* AsyncTask, however you can also use your own @link Executor for custom
* behavior.
*
* <p><em>Warning:</em> Allowing multiple tasks to run in parallel from
* a thread pool is generally <em>not</em> what one wants, because the order
* of their operation is not defined. For example, if these tasks are used
* to modify any state in common (such as writing a file due to a button click),
* there are no guarantees on the order of the modifications.
* Without careful work it is possible in rare cases for the newer version
* of the data to be over-written by an older one, leading to obscure data
* loss and stability issues. Such changes are best
* executed in serial; to guarantee such work is serialized regardless of
* platform version you can use this function with @link #SERIAL_EXECUTOR.
*
* <p>This method must be invoked on the UI thread.
*
* @param exec The executor to use. @link #THREAD_POOL_EXECUTOR is available as a
* convenient process-wide thread pool for tasks that are loosely coupled.
* @param params The parameters of the task.
*
* @return This instance of AsyncTask.
*
* @throws IllegalStateException If @link #getStatus() returns either
* @link AsyncTask.Status#RUNNING or @link AsyncTask.Status#FINISHED.
*/
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;
/**
* Convenience version of @link #execute(Object...) for use with
* a simple Runnable object.
*/
public static void execute(Runnable runnable)
sDefaultExecutor.execute(runnable);
/**
* This method can be invoked from @link #doInBackground to
* publish updates on the UI thread while the background computation is
* still running. Each call to this method will trigger the execution of
* @link #onProgressUpdate on the UI thread.
*
* @link #onProgressUpdate will note be called if the task has been
* canceled.
*
* @param values The progress values to update the UI with.
*
* @see #onProgressUpdate
* @see #doInBackground
*/
protected final void publishProgress(Progress... values)
if (!isCancelled())
sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
private void finish(Result result)
if (isCancelled())
onCancelled(result);
else
onPostExecute(result);
mStatus = Status.FINISHED;
//定义自己的handler
private static class InternalHandler extends Handler
@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;
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result>
Params[] mParams;
@SuppressWarnings("RawUseOfParameterizedType")
private static class AsyncTaskResult<Data>
final AsyncTask mTask;
final Data[] mData;
AsyncTaskResult(AsyncTask task, Data... data)
mTask = task;
mData = data;
以上是源码大概一些方法的意思,关于AsyncTask的执行过程如下
1.当我们在new 自己的异步任务时候会初始化实例化两个类WorkerRunnable ,FutureTask,并且重写WorkerRunnable call方法和FutureTask的done方法。
2.call方法主要执行子类复写的doInBackground,然后调用 postResult显示数据,在postResult里面去调用handler发送数据然后调用finish方法去调用子类的onPostExecute方法,这个时候我们就可以在自己复写的onPostExecute进行ui更新
3.我们需要调用自己异步任务对象的execute方法,execute去调用executeOnExecutor方法在这个方法里面首先会调用onPreExecute();这个方法主要是在doInBackground,方法之前进行调用,做一些初始化工作的,有必要的时候就进行重写即可,方法里面并没有任何代码。第二步会设置mWorker的mParams为我们调用execute时候传进来的参数,最后通过系统默认的Executor 去执行我们自定义的FutureTask,从而执行WorkerRunnable call方法的代码。
其实感觉整个一个类的实现都非常的简单,并不复杂
以上是关于AsyncTask源码解析的主要内容,如果未能解决你的问题,请参考以下文章