AsyncTask2
参考:
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 (
), and most often will override a second one (
.)
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.
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的更多相关文章
- 安卓开发--AsyncTask2
package com.cnn.imageasyncdemo01; import android.app.Activity; import android.content.Intent; import ...
- Promise的前世今生和妙用技巧
浏览器事件模型和回调机制 JavaScript作为单线程运行于浏览器之中,这是每本JavaScript教科书中都会被提到的.同时出于对UI线程操作的安全性考虑,JavaScript和UI线程也处于同一 ...
- Android 结合实例学会AsyncTask的用法
AsyncTask执行时经过四个步骤,执行四个方法: 1.onPreExecute(),运行在UI线程,可以设置或修改UI控件,如显示一个进度条 2.doInBackground,运行在后台线程,不可 ...
- Android 结合实例学会AsyncTask的使用方法
AsyncTask运行时经过四个步骤,运行四个方法: 1.onPreExecute(),执行在UI线程,能够设置或改动UI控件,如显示一个进度条 2.doInB ...
- 使用Promise
Promise所要解决的问题:回调地狱 asyncTask1(data, function (data1){ asyncTask2(data1, function (data2){ asyncTask ...
- Spring boot 使用WebAsyncTask处理异步任务
上文介绍了基于 @Async 注解的 异步调用编程,本文将继续引入 Spring Boot 的 WebAsyncTask 进行更灵活异步任务处理,包括 异步回调,超时处理 和 异常处理. 正文 1. ...
- SpringBoot中Async异步方法和定时任务介绍
1.功能说明 Spring提供了Async注解来实现方法的异步调用. 即当调用Async标识的方法时,调用线程不会等待被调用方法执行完成即返回继续执行以下操作,而被调用的方法则会启动一个独立线程来执行 ...
- Android -- AsyncTask 使用和缺陷
一.AsyncTask的基本用法 由于AsyncTask是一个抽象类,所以如果我们想使用它,就必须要创建一个子类去继承它.在继承时我们可以为AsyncTask类指定三个泛型参数,这三个参数的用途如下: ...
随机推荐
- 关于狗书《Flask web开发 基于python的Web开发应用实战》中加入用户隐私功能
目前是第二次撸狗书,在用户页面这一块我个人觉得有些问题(基于交互设计).按理来说,我作为一个权限只有User的个人用户来说,肯定不喜欢让别人看到我的真实姓名,地址之类的敏感信息.所以我应该是可以设置成 ...
- Node.js实战3:加载一组模块。
有时候,希望通过一个require来加载一个目录下的相关文件. 注:这个方法通常被用来作为组织web应用的架构技巧. 为达到这个目的,需要如此操作: 例:建立一个目录,在此目录中创建一个index.j ...
- Spring-Cloud-Alibaba-Nacos 目录
Spring-Cloud-Alibaba-Nacos 目录 学习资料 Nacos 官网(https://nacos.io/zh-cn/docs/what-is-nacos.html) Nacos 程序 ...
- Spring学习(三)--高级装配
一.Spring profile 在开发软件的时候,有一个很大的挑战就是将应用程序从一个环境迁 移到另外一个环境.开发阶段中,某些环境相关做法可能并不适合迁 移到生产环境中,甚至即便迁移过去也无法正常 ...
- HRESULT是什么类型
HRESULT 是一种简单的数据类型,可以判断函数执行的结果.HRESULT 常被用作COM调用的返回值.充分利用HRESULT返回信息可以帮助提高我们的代码质量,提供程序的健壮性. HRESULT ...
- python学习第十五天字典的创建及增删改查操作方法
字典是python比较常见的数据类型,跟列表一样,比如的字典的创建,字典的常见的操作的方法,增加,删除,修改,查找等方法,字典的一共的数据方法为 keys() values() fromkeys() ...
- C# form 传参数的几个方法
方法一:传值最先想到的,Form2构造函数中接收一个string类型参数,即Form1中选中行的文本,将Form2的TextBox控件的Text设置为该string,即完成了Form1向Form2的传 ...
- 为什么MySQL索引要使用 B+树,而不是其它树形结构?
作者:李平 https://www.cnblogs.com/leefreeman/p/8315844.html 一个问题? InnoDB一棵B+树可以存放多少行数据?这个问题的简单回答是:约2千万 为 ...
- 解决WordPress设置错误的url网站不能访问
由于设置了未备案的域名,而导致网站访问不了了.同时WordPress是使用docker搭建部署的 docker ps #查看 docker 容器 CONTAINER ID IMAGE COMMAND ...
- rabbitMQ实现推迟队列
一. 使用原生Api 1.RabbitMQ 相关 <dependency> <groupId>com.rabbitmq</groupId> <artifact ...