AsyncTask源代码分析

public abstract class AsyncTask<Params, Progress, Result> {

    //日志TAG
private static final String LOG_TAG = "AsyncTask"; //池中所保存的线程数,包括空闲线程。
private static final int CORE_POOL_SIZE = ;
//池中允许的最大线程数。
private static final int MAXIMUM_POOL_SIZE = ;
//当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
private static final int KEEP_ALIVE = ; //一个线程工厂,用来创建新线程 没啥好说的。
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
//这个类是一个线程安全的计数器,用到Unsafe直接与底层打交道。
private final AtomicInteger mCount = new AtomicInteger(); //接口实现的方法,就是给线程起了个名字。
public Thread newThread(Runnable r) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
}
}; //一个固定长度的LinkedBlockingQueue(队列),长度为10。
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(); //一个线程池,关于这个类的细节可以单独研究,这里不细说,就跟连接池的思想一样
//里面维护着一些线程 可以同时处理一些任务。
public static final Executor THREAD_POOL_EXECUTOR
= new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory); //创建一个实现了Executor接口的类 这个类的介绍在下面
public static final Executor SERIAL_EXECUTOR = new SerialExecutor(); //Message的消息类型
private static final int MESSAGE_POST_RESULT = 0x1;
private static final int MESSAGE_POST_PROGRESS = 0x2; //通知主线程的Handler,细节在下面有解释
private static final InternalHandler sHandler = new InternalHandler(); //就是把上面的SERIAL_EXECUTOR拿过来了,和上面的一样
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; //实现了Callable接口 添加了一个参数Params
private final WorkerRunnable<Params, Result> mWorker; //封装具体的任务,这个类的细节可以单独研究 这里也不做细说。
//这个类的特点就是可以取消并且可以监控任务状态
private final FutureTask<Result> mFuture; //将状态设置成【还没开始执行】的状态
private volatile Status mStatus = Status.PENDING; //标记任务是否已经取消,后面的一些方法需要用到。
private final AtomicBoolean mCancelled = new AtomicBoolean();
//标记任务是否已经执行,后面的一些方法需要用到。
private final AtomicBoolean mTaskInvoked = new AtomicBoolean(); //实现Executor接口 对Runnable(任务)在进行一次封装
//这样的实现可以使任务保持连续,即第一个任务执行完毕接着会执行第二个任务
//第二个任务执行在执行第三个任务,以此类推。
private static class SerialExecutor implements Executor {
//一个数组双端队列没有容量限制
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
//当前正在执行的任务
Runnable mActive; //这里进行了synchronized,因为ArrayDeque不是线程安全的,对它的操作需要同步。
public synchronized void execute(final Runnable r) {
//对任务进行包装,然后加入队列的末尾。
mTasks.offer(new Runnable() {
public void run() {
try {
//执行具体任务
r.run();
} finally {
//执行下一个任务【编号001】
scheduleNext();
}
}
});
//如果当前没有执行的任务,则调用scheduleNext开始执行任务
//如果不为null 说明已经有任务在执行,那么就不需要调用scheduleNext
//因为当前任务会被上一个任务在完成时调用。即在【编号001】的位置。
if (mActive == null) {
scheduleNext();
}
} //从队列的头部拿出一个元素,然后执行。这里的任务是在上面包装过的。
//它会先执行具体任务,然后再执行下一个任务
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
} //当前类的状态
public enum Status {
//还没开始执行
PENDING,
//执行中
RUNNING,
//任务完成
FINISHED,
} //没啥用
public static void init() {
sHandler.getLooper();
} //没啥用
public static void setDefaultExecutor(Executor exec) {
sDefaultExecutor = exec;
} //构造参数必须运行在UI线程
public AsyncTask() {
//创建一个WorkerRunnable实例
//这里用到了FutureTask与Callable相关技术。需要自己去研究下
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
//一旦具体任务执行,就将这个标记置为true
mTaskInvoked.set(true);//【编号002】
//设置当前线程优先级为后台线程
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//首先调用doInBackground这个方法 就是我们需要复写的方法。
//然后调用postResult方法 并将doInBackground的返回值传入。
return postResult(doInBackground(mParams));
}
}; //创建一个任务FutureTask,并将上面的mWorker通过构造参数传入。
mFuture = new FutureTask<Result>(mWorker) {
//覆写了done方法,这样当任务的状态发生变化时可以进行监控。
//当任务完成时或取消都进入该方法
@Override
protected void done() {
try {
//通过get方法获取任务的返回结果
//下面就分2中情况
//1-如果上面的call方法正确被调用 那么就执行postResultIfNotInvoked方法
//2-如果任务被取消或者任务执行过程中出现异常则会抛出异常,在下面catch到在进行处理
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
//如果在doInBackground方法中存在异常 这里会继续抛出
throw new RuntimeException("An error occured while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
//如果方法被取消,那么调用postResultIfNotInvoked并传入null
postResultIfNotInvoked(null);
}
}
};
} private void postResultIfNotInvoked(Result result) {
final boolean wasTaskInvoked = mTaskInvoked.get();
//这里判断wasTaskInvoked标记,判断任务是否已经正常结束
//如果在mWorker的call方法正确执行 那么在【编号002】的位置会把wasTaskInvoked设置为true
//这样的话在done()方法中的postResultIfNotInvoked(get());方法才不会重复执行
//也就是说方法如果在mWorker的call方法中执行了 那么在done()中在调用postResultIfNotInvoked(get());
//方法在执行到这的话就不会执行了,反之亦然。
if (!wasTaskInvoked) {
postResult(result);
}
} //该方法是把任务结果发送给UI线程去执行
//就是Looper Handler Message 没啥好说的
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
} //过去当前任务的执行状态
public final Status getStatus() {
return mStatus;
} //需要子类付覆写的方法,后台线程运行。
protected abstract Result doInBackground(Params... params); //在doInBackground方法执行运行,UI线程运行该方法。
//可以启动个进度条之类的操作可以写在这里。
protected void onPreExecute() {
} //UI线程执行,在doInBackground放执行以后执行。
//要注意的是在任务没有出现异常 也没有被取消的情况下才会执行
//否则执行onCancelled
@SuppressWarnings({"UnusedDeclaration"})
protected void onPostExecute(Result result) {
} //运行在UI线程 通过在doInBackground中调用publishProgress方法通知UI线程做一些处理
//比如更新带百分比的进度条等
@SuppressWarnings({"UnusedDeclaration"})
protected void onProgressUpdate(Progress... values) {
} @SuppressWarnings({"UnusedParameters"})
protected void onCancelled(Result result) {
onCancelled();
} //一般子类覆写这个方法 就是cancel方法被调用后 任务被取消 则会执行该方法
protected void onCancelled() {
} //获取任务是否取消
public final boolean isCancelled() {
return mCancelled.get();
} //终止任务
//参数的意义是这样的
//如果线程还没有被启动,那么无论mayInterruptIfRunning是啥 任务都会被取消
//如果任务已经启动 那么如果mayInterruptIfRunning=true 那么会调用线程的
//interrupt方法,这个方法是的解释可以看API 太多了 这里不细说。
public final boolean cancel(boolean mayInterruptIfRunning) {
mCancelled.set(true);
return mFuture.cancel(mayInterruptIfRunning);
} //这个方法获取任务的结果,是一个阻塞方法
//属于FutureTask的范畴
public final Result get() throws InterruptedException, ExecutionException {
return mFuture.get();
} //同上
public final Result get(long timeout, TimeUnit unit) throws InterruptedException,
ExecutionException, TimeoutException {
return mFuture.get(timeout, unit);
} //启动任务
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
//调用executeOnExecutor
return executeOnExecutor(sDefaultExecutor, params);
} //这个方法是AsyncTask的启动方法,用来启动任务
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
//判断任务的状态 如果不是PENDING状态则抛出异常
//也就是说任务只能启动一次,不可重复启动。
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)");
}
} //设置任务状态为RUNNING
mStatus = Status.RUNNING;
//调用预处理方法上面解释过。
onPreExecute();
//给mWorker设置参数
mWorker.mParams = params;
//将任务加入到sDefaultExecutor当中去执行
exec.execute(mFuture);
//返回自己
return this;
} //这个方法是用过sDefaultExecutor执行直接执行一个Runnable接口,去AsyncTask没啥关系
//无非就是用到了sDefaultExecutor
public static void execute(Runnable runnable) {
sDefaultExecutor.execute(runnable);
} //这个方法可以通知UI线程更新进度
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
} //任务完成后调用的方法,会根据isCancelled()的返回值判断任务是否被取消或者正常执行成功。
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[]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
} //一个抽象类实现了Callable<Result>接口 添加了参数。
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 核心原理大概如下

InternalHandler sHandler = new InternalHandler(); 这个handler是主线程初始化的,用来调用更新UI的方法。

THREAD_POOL_EXECUTOR 一个线程池用来处理异步任务。

sPoolWorkQueue 一个任务队列,我们发起的所有任务都会放到这个队列当中,由THREAD_POOL_EXECUTOR 它来进行处理。

流程就是当我们创建一个AsyncTask实例 ,那么AsyncTask会生成一个任务对象(Runnable)放入sPoolWorkQueue 这个队列当中,然后有THREAD_POOL_EXECUTOR 线程池去进行异步处理,在处理的过程中通过sHandler 通知主线程去调用我们复写的那几个方法更新UI。

这个类在设计当中还使用到了 FutureTask

关于这个类的源码分析请看我的另外一个博客:http://www.cnblogs.com/daxin/p/3802392.html

Android AsyncTask 源代码分析的更多相关文章

  1. Android异步任务处理框架AsyncTask源代码分析

    [转载请注明出处:http://blog.csdn.net/feiduclear_up CSDN 废墟的树] 引言 在平时项目开发中难免会遇到异步耗时的任务(比方最常见的网络请求).遇到这样的问题.我 ...

  2. Android 消息处理源代码分析(1)

    Android 消息处理源代码分析(1) 在Android中,通常被使用的消息队列的代码在文件夹\sources\android-22\android\os下,涉及到下面几个类文件 Handler.j ...

  3. Android HandlerThread 源代码分析

    HandlerThread 简单介绍: 我们知道Thread线程是一次性消费品,当Thread线程运行完一个耗时的任务之后.线程就会被自己主动销毁了.假设此时我又有一 个耗时任务须要运行,我们不得不又 ...

  4. Android HttpURLConnection源代码分析

    Android HttpURLConnection源代码分析 之前写过HttpURLConnection与HttpClient的差别及选择.后来又分析了Volley的源代码. 近期又遇到了问题,想在V ...

  5. Android KLog源代码分析

    Android KLog源代码分析 Android KLog源代码分析 代码结构 详细分析 BaseLog FileLog JsonLog XmlLog 核心文件KLogjava分析 遇到的问题 一直 ...

  6. android开发源代码分析--多个activity调用多个jni库的方法

    android开发源代码分析--多个activity调用多个jni库的方法 有时候,我们在开发android项目时会遇到须要调用多个native c/jni库文件,下面是本人以前实现过的方法,假设有知 ...

  7. Android 消息处理源代码分析(2)

    Android 消息处理源代码分析(1)点击打开链接 继续接着分析剩下的类文件 Looper.java public final class Looper { final MessageQueue m ...

  8. Appium Android Bootstrap源代码分析之启动执行

    通过前面的两篇文章<Appium Android Bootstrap源代码分析之控件AndroidElement>和<Appium Android Bootstrap源代码分析之命令 ...

  9. Android `AsyncTask`简要分析

    AsyncTask简要分析 经典异步任务:AsyncTask,使用场景有:批量下载,批量拷贝等.官方文档就直接给出了一个批量下载的示例. private class DownloadFilesTask ...

随机推荐

  1. Java面试基础部分合集

    写在前面:这篇文章对于在Java方面已经很牛逼的大手,就没必要看了,因为对于你们来说,这tm简直太简单了.... 面试我们都经历过,你真的懂面试吗?针对面试我只想说一点,面试的目的不是让考官知道你怎么 ...

  2. 使用Apache FtpServer

    Java大法一统天下.遇到任何问题,先查一下Java中的解决方案. 地球上的许多事情,在Java中都能找到完美的解决方案. FtpServer是apache MINA项目的一个子项目,它实现了一个ft ...

  3. Python的 numpy中 meshgrid 和 mgrid 的区别和使用

    一.meshgrid函数 meshgrid函数通常使用在数据的矢量化上. 它适用于生成网格型数据,可以接受两个一维数组生成两个二维矩阵,对应两个数组中所有的(x,y)对. 示例展示: 由上面的示例展示 ...

  4. PHP 大数自动转换为科学计数法

    前段时间碰到一个很头疼的问题,就是大于12位的数字在PHP中,会自动转成科学计数法表 示. 比如 1234567891234 显示为 1.23456789123E+12 , 最后只能在计算出大数之后, ...

  5. Android Developers:使ListView滑动流畅

    流畅滑动ListView的关键是保持应用程序的主线程(UI线程)从免于繁重处理.确保你的任何硬盘访问,网络访问或者SQL访问在一个单独的线程中.为了测试你的应用个程序的状态,你能启动StrictMod ...

  6. Windows下面安装和配置Solr 4.9(二)

    将Solr和Tomcat结合: 1.在D盘下创建目录 D:\Demos\Solr 2.解压solr-4.9.0文件,我这里下载的是这个4.9版本,将example文件夹下的solr文件夹中的所有文件( ...

  7. Java编程性能优化一些事儿【转】

    原文出处: 陶邦仁 在JAVA程序中,性能问题的大部分原因并不在于JAVA语言,而是程序本身.养成良好的编码习惯非常重要,能够显著地提升程序性能. 1. 尽量在合适的场合使用单例 使用单例可以减轻加载 ...

  8. uploadify上传图片

    1.实现源代码 <%@ page language="java" import="java.util.*" pageEncoding="UTF- ...

  9. jdbc与odbc的差别,感悟,学习。。。

    什么是JDBC? JDBC, 全称为Java DataBase Connectivity standard, 它是一个面向对象的应用程序接口(API), 通过它可訪问各类关系数据库.JDBC也是jav ...

  10. 最常用的五类CSS选择器

    一些新手朋友对选择器一知半解,不知道在什么情况下运用什么样的选择器,这是一个比较头疼的问题,针对新手朋友,对CSS选择器作一些简单的说明,希望能对大家的学习工作有一定的帮助,更多的CSS知识请参考We ...