参考:

AsyncTask - 简书
http://www.jianshu.com/p/3b839d7a3fcf

前言

在android应用开发过程中,我们需要是时刻注意保证应用程序的稳定和UI操作响应及时,不稳定或响应不及时会带来不好的用户体验。

为何要引入AsyncTask?

在Android程序开始运行的时候会单独启动一个进程,默认情况下所有这个程序操作都在这个进程中进行。一个Android程序默认情况下只有一个进程,但一个进程中可以有多个线程。

在这些线程中,有一个线程叫做UI线程(也叫Main Thread),除了UI线程外的线程都叫子线程(Worker Thread)。UI线程主要负责控制UI界面的显示、更新、交互等。因此,UI线程中的操作延迟越短越好(流畅)。把一些耗时的操作(网络请求、数据库操作、逻辑计算等)放到单独的线程,可以避免主线程阻塞。

Android给我们提供了一种轻量级的异步任务类AsyncTask。该类中实现异步操作,并提供接口反馈当前异步执行结果及进度,这些接口中有直接运行在主线程中的(如 onPostExecute,onPreExecute等)。

API

 

官方文档

百度翻译:

AsyncTask使适当的和易用的UI线程。这个类可以执行后台操作,并在用户界面上发布结果,而不必处理线程和/或处理程序。

AsyncTask的设计是围绕线程和处理器的一个辅助类,并不构成一个通用的线程框架。asynctasks应该用于短作业(最多。几秒钟)如果你需要保持线程运行很长一段时间,我们强烈建议您使用不同的java.util.concurrent包如执行API提供的,线程池和futuretask。

异步任务被定义为一个在后台线程上运行的运算,其结果是在用户界面上发布的。一个异步任务是由3的泛型类型定义为参数,过程和结果,和4个步骤,称为onpreexecute,doInBackground,onProgressUpdate和onpostexecute。

使用(API)

AsyncTask must be subclassed to be used. The subclass will override at least one method (

doInBackground(Params...)

), and most often will override a second one (

onPostExecute(Result)

.)

AsyncTask必须被子类继承使用。子类至少重写一个方法(doInBackground(Params...)),和最经常会重写第二个方法(onPostExecute(result))

使用案例

调用方式

AsyncTask的泛型

一个异步任务使用的三种类型如下:

1.Params,the type of the parameters sent to the task upon execution.(参数的类型发送到任务执行时。)

网络访问时可以做String来传URI。

2.Progress,the type of the progress units published during the background computation.(后台计算过程中的进度单元类型。)

进度条参数。onProgressUpdate方法可以用这个参数来更新进度条。

3.Result,the type of the result of the background computation.(后台运行的结果类型。)

Result参数可以存储从网络上面获取的数据。

doInBackground将result参数传递给onpostexecute,onpostexecute方法可以用这个参数来更新界面。

Not all types are always used by an asynchronous task. To mark a type as unused, simply use the typeVoid:(不是所有的参数都需要,不用时可以返回void类型)

 

源码:

AsyncTask内部逻辑主要有二部分:

1.与主线程交互,它内部实例化一个静态的自定义类InternalHandler,这个类是继承Handler的,在这个自定义类中绑定了一个叫做AsyncTaskResult的对象,每次子线程需要通知主线程,就调用sendToTarget发消息给handle,然后在handle的handleMessage中AsyncTaskResult根据消息的类型不同(如MESSAGE_POST_PROGRESS会更新进度条,MESSAGE_POST_CANCEL取消任务)而做这些操作都是在UI线程进行的。意味着,从子线程一旦需要和UI线程交互,内部自动调用了handler对象把消息放在主线程。(onProgressUpdate用于更新界面任务进度)

 

 

2.AsyncTask内部调用,虽然可以新建多个AsyncTask的子类实例,但是AsyncTask内部Handler和ThreadPoolExecutor都是static,这么定义是进程范围内共享的,所以AsyncTask控制着的进程范围内所有的子类实例,且该类的所有实例都共用一个线程池(serialExecutor和THREAD_POOL_EXECUTOR)和 另一个线程池Handler(InternalHandler)。

 

 

从代码可以看出,默认核心线程池的大小CORE_POOL_SIZE是根据Runtime.getRuntime().availableProcessors()获取设备的核数(比如你手机双核返回2),通常线程池的大小是默认期望的并发数。如:默认核心线程池大小5。意味着,如果线程池数量小于5,这时候新添加一个异步任务则会新建一个线程,如果数量大于等于5,这时候新建的异步任务会被放入缓存队列中等待。限制APP内AsyncTask并发的线程是有必要的。同时运行任务多,线程多,会导致短时间内手机内存被占完!

事实上,从android 3.0开始,每次新建异步任务的时候AsyncTask内部默认规则是按提交的先后顺序每次只运行一个异步任务。当然你也可以自己指定自己的线程池。

AsyncTask的工作原理

1.从他的execute方法开始分析,会调用executeOnExecutor();其中AsyncTask的onPreExecute方法是最先执行的,然后线程池开始执行。

 

 

同上

2.从代码看,sDefaultExecutor实际上是一个串行的线程池,一个进程中所有的AsyncTask全部都在这个线程池中执行。从SerialExecutor的实现分析AsyncTask的排队执行的过程。

首先系统会把AsyncTask的参数封装为FutureTask对象,FutureTask是一个并发类,在这里它充当了Runnable的作用。

接着这个FutureTask会交给SerialExecutor的execute方法处理,execute方法会先把FutureTask对象插入到任务队列mTask中,如果这时没有正在活动的任务,那么就会调用SeriaExecutor的scheduleNext()类执行下个任务。同一个AsyncTask任务执行完后,AsyncTask会继续执行其他任务知道所有任务都被执行完,从这一点可以看出,默认情况下AsyncTask是串行执行的。

 

同上

3.不行看得想吐了!W~u ~a~a.....

Note:

1.由于Handler需要和主线程交互,而Handler又是内置于AsyncTask中,所有AsyncTask的创建必须在主线程。

2.AsyncTaskResult的doInBackground(Params)方法执行异步任务运行在子线程中,其他方法运行在主线程中,可以操作UI组件。

3.不要手动的去调用AsyncTask的onPreExecute, doInBackground, publishProgress, onProgressUpdate, onPostExecute方法,这些都是由android系统自动调用的。

4.一个AsyncTask任务只能被执行一次。

5.运行中可以随时调用cancel(boolean)方法取消任务,如果成功调用isCancel()会返回true,并不会执行onPostExecute(),取而代之的是调用onCancelled()。从源码看,如果这个任务已经执行了这个时候调用cancel是不会真正的把task结束,而是继续执行,只不过改变的是执行之后的回调方法的onPostExecute还是onCancelled.

 
Note第三点,publishProgress是需要用户手动调用的。onProgressUpdate使用publishProgress方法中的参数。

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

sHandler进度消息发送,

case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);

此处处理消息,系统调用重写的onProgressUpdate来更新进度。

AsyncTask2的更多相关文章

  1. 安卓开发--AsyncTask2

    package com.cnn.imageasyncdemo01; import android.app.Activity; import android.content.Intent; import ...

  2. Promise的前世今生和妙用技巧

    浏览器事件模型和回调机制 JavaScript作为单线程运行于浏览器之中,这是每本JavaScript教科书中都会被提到的.同时出于对UI线程操作的安全性考虑,JavaScript和UI线程也处于同一 ...

  3. Android 结合实例学会AsyncTask的用法

    AsyncTask执行时经过四个步骤,执行四个方法: 1.onPreExecute(),运行在UI线程,可以设置或修改UI控件,如显示一个进度条 2.doInBackground,运行在后台线程,不可 ...

  4. Android 结合实例学会AsyncTask的使用方法

    AsyncTask运行时经过四个步骤,运行四个方法:           1.onPreExecute(),执行在UI线程,能够设置或改动UI控件,如显示一个进度条           2.doInB ...

  5. 使用Promise

    Promise所要解决的问题:回调地狱 asyncTask1(data, function (data1){ asyncTask2(data1, function (data2){ asyncTask ...

  6. Spring boot 使用WebAsyncTask处理异步任务

    上文介绍了基于 @Async 注解的 异步调用编程,本文将继续引入 Spring Boot 的 WebAsyncTask 进行更灵活异步任务处理,包括 异步回调,超时处理 和 异常处理. 正文 1. ...

  7. SpringBoot中Async异步方法和定时任务介绍

    1.功能说明 Spring提供了Async注解来实现方法的异步调用. 即当调用Async标识的方法时,调用线程不会等待被调用方法执行完成即返回继续执行以下操作,而被调用的方法则会启动一个独立线程来执行 ...

  8. Android -- AsyncTask 使用和缺陷

    一.AsyncTask的基本用法 由于AsyncTask是一个抽象类,所以如果我们想使用它,就必须要创建一个子类去继承它.在继承时我们可以为AsyncTask类指定三个泛型参数,这三个参数的用途如下: ...

随机推荐

  1. 【ABAP系列】SAP ABAP 物料凭证增强

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP 物料凭证增强 ...

  2. poj3669 Meteor Shower (宽度优先搜索)

    Description - 题目描述 Bessie听说有场史无前例的流星雨即将来临:有谶言:陨星将落,徒留灰烬.为保生机,她誓将找寻安全之所(永避星坠之地).目前她正在平面坐标系的原点放牧,打算在群星 ...

  3. 爬虫之requests 高级用法

    1. 文件上传 import requests files = {'file': open('favicon.ico', 'rb')} r = requests.post("http://h ...

  4. FastReport使用教程

    FastReport使用心得 一.准备 1.这次开发使用的是FastReport桌面版(FastReport.Net Version 201731.16 Demo) 2.引用类库FastReport. ...

  5. JavaScript高级程序设计(第3版) 第四章(变量、作用域和内存问题)

    4.1 基本类型和引用类型的值             1.基本类型的值是(简单的数据段),引用类型的值是(保存在内存中的对象). 基本类型的值在内存中占据固定大小的空间,因此被保存在栈中.(lifo ...

  6. spring的4种事务特性,4种隔离级别,7种传播行为

    spring事务: 什么是事务: 事务逻辑上的一组操作,组成这组操作的各个逻辑单元,要么一起成功,要么一起失败. 事务特性(4种): 原子性 (atomicity):强调事务的不可分割. 一致性 (c ...

  7. 使用Angular2+的内置管道格式化数据

    在简书看到一篇关于Angualr运用内置管道格式化数据的总结,感觉挺实用的,转载一下以供参考: [转载]https://www.jianshu.com/p/a8bd5a1d2c53 PS:管道是在HT ...

  8. Q480S-I7 D1 笔记本使用 VS2015 运行性能探查器会导致电脑自动重启?

    漏洞导致 https://www.freebuf.com/vuls/159642.html 使用以下两句 无法修复该问题,建议升级 win10 系统,使用 vs2017 reg add "H ...

  9. 构建自己的AngularJS,第一部分:作用域和digest 转摘:http://www.ituring.com.cn/article/39865

    构建自己的AngularJS,第一部分:Scope和Digest 原文链接:http://teropa.info/blog/2013/11/03/make-your-own-angular-part- ...

  10. vector中数据释放崩溃问题

    struct LINE { char securityID[32]; /*!< 证券代码 */ int64_t dateTime; /*!< 日期时间(日期变化)YYYYMMDDhhmms ...