AsyncTask

new AsyncTask<String,String,String>(){
// 运行在主线程中,做预备工作
onPreExecute(){ }
// 运行在子线程中,做耗时操作
String doingBackGround(String s){ }
// 运行在主线程中,耗时操作完成,更新UI
onPostExecute(String s){ } }.execute(String);

AsyncTask的execute方法

public final AsyncTask<Params, Progress, Result> execute(Params... params) {
... mStatus = Status.RUNNING;
// 在主线程中执行准备操作
onPreExecute();
// 把params参数赋值给mWorker
mWorker.mParams = params;
// 用线程池执行mFuture
sExecutor.execute(mFuture); // 在AsyncTask构造方法中创建了mWorker
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
...
}
}; mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
...
}
};
}
// 把mWorker传递给FutureTask,callable指的就是mWorker
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
sync = new Sync(callable);
}
// 把mWorker传递给Sync,callable指的是mWorker
Sync(Callable<V> callable) {
this.callable = callable;
}

线程池执行FutureTask,就是执行FutureTask的run方法,代码如下:

    public void run() {
// 转调
sync.innerRun();
} void innerRun() {
if (!compareAndSetState(READY, RUNNING))
return; runner = Thread.currentThread();
if (getState() == RUNNING) { // recheck after setting thread
V result;
try {
// 就是调用了mWorker.call方法
// 把耗时操作得到的结果赋值给result
result = callable.call();
} catch (Throwable ex) {
setException(ex);
return;
}
// 转调了sync.innerSet(v);
set(result);
} else {
releaseShared(0); // cancel
}
} mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
// 执行耗时操作 在子线程中执行
return doInBackground(mParams);
}
}; protected void set(V v) {
// 转调
sync.innerSet(v);
} void innerSet(V v) {
for (;;) {
int s = getState();
if (s == RAN)
return;
if (s == CANCELLED) {
// aggressively release to set runner to null,
// in case we are racing with a cancel request
// that will try to interrupt runner
releaseShared(0);
return;
}
if (compareAndSetState(s, RAN)) {
result = v;
releaseShared(0);
// 调用了FutureTask的抽象方法
done();
return;
}
}
} mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
Message message;
Result result = null; try {
// 转调了sync.innerGet()
result = 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) {
message = sHandler.obtainMessage(MESSAGE_POST_CANCEL,
new AsyncTaskResult<Result>(AsyncTask.this, (Result[]) null));
message.sendToTarget();
return;
} catch (Throwable t) {
throw new RuntimeException("An error occured while executing "
+ "doInBackground()", t);
}
// 发送了一个Message
message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(AsyncTask.this, result));
message.sendToTarget();
}
}; public V get() throws InterruptedException, ExecutionException {
// 转调
return sync.innerGet();
} V innerGet() throws InterruptedException, ExecutionException {
acquireSharedInterruptibly(0);
if (getState() == CANCELLED)
throw new CancellationException();
if (exception != null)
throw new ExecutionException(exception);
// 把之前doinBackground方法的结果返回
return result;
}

在AsyncTask的成员变量,创建了InternalHandler

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
// 结束耗时操作完成后的消息
// 调用了AsyncTask的finish方法传递的result.mData[0]就是之前
// 耗时操作返回来的结果
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
case MESSAGE_POST_CANCEL:
result.mTask.onCancelled();
break;
}
}
}
private static class AsyncTaskResult<Data> {
final AsyncTask mTask;
final Data[] mData;
// data 是返回的结果
AsyncTaskResult(AsyncTask task, Data... data) {
mTask = task;
mData = data;
}
} private void finish(Result result) {
if (isCancelled()) result = null;
// 耗时操作完成,更新UI,执行在主线程
onPostExecute(result);
mStatus = Status.FINISHED;
}

源码篇——AsyncTask机制的更多相关文章

  1. 鸿蒙内核源码分析(调度机制篇) | 任务是如何被调度执行的 | 百篇博客分析OpenHarmony源码 | v7.07

    百篇博客系列篇.本篇为: v07.xx 鸿蒙内核源码分析(调度机制篇) | 任务是如何被调度执行的 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调 ...

  2. 源码篇:SDWebImage

    攀登,一步一个脚印,方能知其乐 源码篇:SDWebImage 源码来源:https://github.com/rs/SDWebImage 版本: 3.7 SDWebImage是一个开源的第三方库,它提 ...

  3. springMVC源码分析--异常处理机制HandlerExceptionResolver执行原理(二)

    上一篇博客springMVC源码分析--异常处理机制HandlerExceptionResolver简单示例(一)中我们简单地实现了一个异常处理实例,接下来我们要介绍一下HandlerExceptio ...

  4. Dubbo 源码分析 - SPI 机制

    1.简介 SPI 全称为 Service Provider Interface,是 Java 提供的一种服务发现机制.SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加 ...

  5. MyBatis 源码分析 - 插件机制

    1.简介 一般情况下,开源框架都会提供插件或其他形式的拓展点,供开发者自行拓展.这样的好处是显而易见的,一是增加了框架的灵活性.二是开发者可以结合实际需求,对框架进行拓展,使其能够更好的工作.以 My ...

  6. spring-boot-2.0.3启动源码篇二 - run方法(一)之SpringApplicationRunListener

    前言 Springboot启动源码系列还只写了一篇,已经过去一周,又到了每周一更的时间了(是不是很熟悉?),大家有没有很期待了?我会尽量保证启动源码系列每周一更,争取不让大家每周的期望落空.一周之中可 ...

  7. spring-boot-2.0.3启动源码篇 - 阶段总结

    前言 开心一刻 朋友喜欢去按摩,第一次推门进来的是一个学生美眉,感觉还不错:后来经常去,有时是护士,有时是空姐,有时候是教师.昨天晚上推门进去的是一个女警察,长得贼好看,身材也很好,朋友嗷的一声就扑上 ...

  8. MySQL Master High Available 源码篇

    https://m.aliyun.com/yunqi/users/1287368569594542/articles https://yq.aliyun.com/articles/59233 MySQ ...

  9. MyBatis 源码篇-整体架构

    MyBatis 的整体架构分为三层, 分别是基础支持层.核心处理层和接口层,如下图所示. 基础支持层 反射模块 该模块对 Java 原生的反射进行了良好的封装,提供了更加简洁易用的 API ,方便上层 ...

随机推荐

  1. WebRTC 音频采样算法 附完整C++示例代码

    之前有大概介绍了音频采样相关的思路,详情见<简洁明了的插值音频重采样算法例子 (附完整C代码)>. 音频方面的开源项目很多很多. 最知名的莫过于谷歌开源的WebRTC, 其中的音频模块就包 ...

  2. php array_multisort函数实现按某一字段对二维数组进行排序

    在工作中碰到一个页面如表格似的展示多条数据,要求根据其中的修改时间对数据进行排序, 数据格式类似于 $a = array( 0=>array( editTime=>'' addTime=& ...

  3. codefroces 297E Mystic Carvings

    problem:一个圆上依次有1~2*n的数字.每个数字都有且只有另一个数字与他相连.选出三条线,使得每条线的两端之间隔的最少点(只包括被选择的6个点)的个数相等.输入输出格式输入格式: The fi ...

  4. codeforces 815C Karen and Supermarket

    On the way home, Karen decided to stop by the supermarket to buy some groceries. She needs to buy a ...

  5. [ZJOI2011]看电影(MOVIE)

    题目描述 到了难得的假期,小白班上组织大家去看电影.但由于假期里看电影的人太多,很难做到让全班看上同一场电影,最后大家在一个偏僻的小胡同里找到了一家电影院.但这家电影院分配座位的方式很特殊,具体方式如 ...

  6. LOJ #6119. 「2017 山东二轮集训 Day7」国王

    Description 在某个神奇的大陆上,有一个国家,这片大陆的所有城市间的道路网可以看做是一棵树,每个城市要么是工业城市,要么是农业城市,这个国家的人认为一条路径是 exciting 的,当且仅当 ...

  7. ICM Technex 2017 and Codeforces Round #400 (Div. 1 + Div. 2, combined)

    前四题比较水,E我看出是欧拉函数傻逼题,但我傻逼不会,百度了下开始学,最后在加时的时候A掉了 AC:ABCDE Rank:182 Rating:2193+34->2227 终于橙了,不知道能待几 ...

  8. bzoj1071[SCOI2007]组队

    1071: [SCOI2007]组队 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 2472  Solved: 792[Submit][Status][ ...

  9. Entity Framework DBContext 增删改查深度解析

    Entity Framework DBContext 增删改查深度解析 有一段时间没有更新博客了,赶上今天外面下雨,而且没人约球,打算把最近对Entity Framework DBContext使用的 ...

  10. linux退出状态码及exit命令

    Linux提供了一个专门的变量$?来保存上个已执行命令的退出状态码.对于需要进行检查的命令,必须在其运行完毕后立刻查看或使用$?变量.它的值会变成由shell所执行的最后一条命令的退出状态码: [ro ...