AsyncTask源码解析
package com.example.demo.activity.net; import java.util.ArrayDeque;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.FutureTask;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.os.Process; public abstract class MyAsyncTask<Params, Progress, Result> {
private static final String LOG_TAG = "AsyncTask";
// 返回cpu的数目
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// 设置核心线程数量
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
// 设置最大线程数量
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 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());
}
}; private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(128); // 创建了一个线程池,传入参数为核心线程2,最多线程3,休息时间1秒,容纳128个线程对象的队列,线程工厂
public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
// 创建一个串行执行任务对象
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
// handler接受码
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;
// 继承了一个泛型的回掉接口,在mFuture的run方法中会调用mWorker的call回调方法
private final WorkerRunnable<Params, Result> mWorker;
// 线程对象,实现了RunnableFuture接口
private final FutureTask<Result> mFuture; private volatile Status mStatus = Status.PENDING;
// 判断是否已经主动取消执行中的任务
private final AtomicBoolean mCancelled = new AtomicBoolean();
// 判断
private final AtomicBoolean mTaskInvoked = new AtomicBoolean(); // 判断是否正常调用postResult(doInBackground(mParams))
private static class SerialExecutor implements Executor {
// 维护的队列,每execute一次就offer进来一个mFuture线程对象
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive; public synchronized void execute(final Runnable r) {
// 默认的execute提交就是把封装的mFuture用该方法提交,所有提交的线程对象都先存放在该队列中
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
// 队列中所有线程对象都执行完之后,mActive = mTasks.poll()就会等于null
// 然后新加入的任务又会重新启动执行
if (mActive == null) {
scheduleNext();
}
} // 从队列中获取一个线程对象,将他放到线程池中执行,执行完之后就会接着调用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();
} /**
* 设置默认的线程池
*
* @param exec
*/
public static void setDefaultExecutor(Executor exec) {
sDefaultExecutor = exec;
} /**
* 构造函数,初始化了mFuture线程对象,并封装了mWorker回调接口
*/
public MyAsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true); Process.setThreadPriority(10);
// noinspection unchecked
return postResult(doInBackground(mParams));
}
};
// 被强行打断,出异常,或者正常结束都会调用下面的done(),
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 occured while executing doInBackground()", e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
} // 正常结束,出异常,被强行打断就会调用下面的方法
// 但是正常结束不会调用里面的postResult(result)。因为他已经在call()中调用
private void postResultIfNotInvoked(Result result) {
final boolean wasTaskInvoked = mTaskInvoked.get();
if (!wasTaskInvoked) {
postResult(result);
}
} /**
* 使用handler往主线程中发送返回结果
*
* @param result
* @return
*/
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
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
*/
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
*/
@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 mCancelled.get();
} /**
* <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)
*/
/**
* 外部强行打断任务执行的时候调用,正常结束不用调用
*
* @param mayInterruptIfRunning
* @return
*/
public final boolean cancel(boolean mayInterruptIfRunning) {
mCancelled.set(true);
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. Starting
* {@link android.os.Build.VERSION_CODES#HONEYCOMB}, tasks are back to being executed on 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}.
*
* @see #executeOnExecutor(java.util.concurrent.Executor, Object[])
* @see #execute(Runnable)
*/
/**
* 使用默认的串行执行
*
* @param params
* @return
*/
public final MyAsyncTask<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}.
*
* @see #execute(Object[])
*/
/**
* 可以使用该类里面提供的线程池来执行任务
*
* @param exec
* @param params
* @return
*/
public final MyAsyncTask<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. See {@link #execute(Object[])} for more information on the order of execution.
*
* @see #execute(Object[])
* @see #executeOnExecutor(java.util.concurrent.Executor, Object[])
*/
/**
* 使用默认的串行来执行线程对象
*
* @param runnable
*/
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 not be called if the task has been canceled.
*
* @param values
* The progress values to update the UI with.
*
* @see #onProgressUpdate
* @see #doInBackground
*/
/**
* 如果已经被取消,就不会发送更新进度条
*
* @param values
*/
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
sHandler.obtainMessage(MESSAGE_POST_PROGRESS, new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
} /**
* 在handler中判断,如果已经被取消就调用onCancelled(result),正常结束调用onPostExecute(result)
*
* @param result
*/
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
} /**
* handler对象
*
* @author liulj
*
*/
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;
} /**
* handler中传递的对象
*
* @author liulj
*
* @param <Data>
*/
@SuppressWarnings({ "RawUseOfParameterizedType" })
private static class AsyncTaskResult<Data> {
final MyAsyncTask mTask;
final Data[] mData; AsyncTaskResult(MyAsyncTask task, Data... data) {
mTask = task;
mData = data;
}
}
}
AsyncTask源码解析的更多相关文章
- Android AsyncTask 源码解析
1. 官方介绍 public abstract class AsyncTask extends Object java.lang.Object ↳ android.os.AsyncTask&l ...
- Android -- AsyncTask源码解析
1,前段时间换工作的时候,关于AsyncTask源码这个点基本上大一点的公司都会问,所以今天就和大家一起来总结总结.本来早就想写这篇文章的,当时写<Android -- 从源码解析Handle+ ...
- Android开发——AsyncTask的使用以及源码解析
.AsyncTask使用介绍 转载请标明出处:http://blog.csdn.net/seu_calvin/article/details/52172248 AsyncTask封装了Thread和 ...
- Android源码解析——AsyncTask
简介 AsyncTask 在Android API 3引入,是为了使UI线程能被正确和容易地使用.它允许你在后台进行一些操作,并且把结果带到UI线程中,而不用自己去操纵Thread或Handler.它 ...
- 小白挑战:AsyncTask源码分析
//AsyncTask从本质上讲,是对ThreadPool和handler的封装. 在学习线程池相关的知识时,看到书中提到AsyncTask的实现中使用到了ThreadPool,于是把源码翻了出来, ...
- Android Asynctask与Handler的比较,优缺点区别,Asynctask源码
1 AsyncTask实现的原理,和适用的优缺点 AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以 ...
- 【转载】Xutils3源码解析
Github源码地址:https://github.com/wyouflf/xUtils3 原文地址 :http://www.codekk.com/blogs/detail/54cfab086c476 ...
- Android源码解析系列
转载请标明出处:一片枫叶的专栏 知乎上看了一篇非常不错的博文:有没有必要阅读Android源码 看完之后痛定思过,平时所学往往是知其然然不知其所以然,所以为了更好的深入Android体系,决定学习an ...
- 还怕问源码?Github上神级Android三方源码解析手册,已有7.6 KStar
或许对于许多Android开发者来说,所谓的Android工程师的工作"不过就是用XML实现设计师的美术图,用JSON解析服务器的数据,再把数据显示到界面上"就好了,源码什么的,看 ...
随机推荐
- OEM代工厂产品经理个人经历谈
创业不是一件随随便便的事情! 到2007年时,我已经在上海.广州.东莞三地的工厂打工有十来年了.正是这个时间结点,我也即将做父亲了.打了很久的工后,就开始感到疲倦,做来做去,都是给老板做,也就在这时开 ...
- eclipse js提醒报错
在用eclipse开发项目时,有时候导入项目后,报错为 Problem Occurred: Errors occurred during the build. Errors running bu ...
- mysql metadata lock(一)
想必玩过mysql的人对Waiting for table metadata lock肯定不会陌生,一般都是进行alter操作时被堵住了,导致了我们在show processlist 时,看到线程的状 ...
- mvn archetype:create和mvn archetype:generate
create is deprecated in maven 3.0.5 and beyond,在maven3.0.5以上版本舍弃了create,使用generate生成项目 before:mvn ar ...
- itext 实现pdf打印数字上标和下标
https://kathleen1974.wordpress.com/category/itext-pdf/ In one of my project, we need to give the use ...
- 与POS机通信时的3DES(双倍长)加密解密
项目中有个SocketServer要和移动便携POS机通信,POS开发商就告诉我们他们用的3DES(双倍长)加密,给了个Key.数据和结果,让我们实现. c#用TripleDESCryptoServi ...
- python中mysqldb的用法
1.引入MySQLdb库 import MySQLdb 2.和数据库建立连接 conn=MySQLdb.connect(host="localhost",user="ro ...
- 透过byte数组简单分析Java序列化、Kryo、ProtoBuf序列化
序列化在高性能网络编程.分布式系统开发中是举足轻重的之前有用过Java序列化.ProtocolBuffer等,在这篇文章这里中简单分析序列化后的byte数组观察各种序列化的差异与性能,这里主要分析Ja ...
- cat,tac,more
cat VS tac cat是查看文本文件的内容,tac是cat反过来,反向查看文件 $cat 1.txt ls: cannot access ee: No such file or director ...
- C/C++ sizeof函数解析——解决sizeof求结构体大小的问题
C/C++中不同数据类型所占用的内存大小 32位 64位 char 1 1 int ...