AsyncTask使用详细说明
AsyncTask使用:
在开发Android应用时必须遵守单线程模型的原则: Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。在单线程模型中始终要记住两条法则:
1. 不要阻塞UI线程
2. 确保只在UI线程中更新界面
当一个程序第一次启动时,Android会同时启动一个对应的主线程(Main Thread),主线程主要负责处理与UI相关的事件,如:用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理。所以主线程通常又被叫做UI线程。
为了不阻塞UI线程, 一些比较耗时的操作, 如网络下载, 数据库读取等操作需要放到work thread中去执行, 当执行完后, 如果需要更新UI界面, 可以通过以下几种方法进行:
1. Activity.runOnUiThread( Runnable )
2. View.post( Runnable )
3. View.postDelayed( Runnable, long )
4. Hanlder(在UI线程中定义的对象)
这些类或方法同样会使你的代码很复杂很难理解。然而当你需要实现一些很复杂的操作并需要频繁地更新UI时这会变得更糟糕。
为了解决这个问题,Android 1.5提供了一个工具类:AsyncTask,它使得work thread(用户自定义的后台执行耗时操作的线程)和UI thead 之间的交互变得简单清晰。
AsyncTask是抽象类, 使用时需要派生一个子类, 如下:
Public class QAsyncTask extends AsyncTask<Params, Progress, Result> {
}
AsyncTask定义了三个泛型数据Params,Progress和Result, 作用如下:
Params:
启动task时传入的参数, 如new QAsyncTask().execute(Params), 这个输入参数是task执行过程中的调用函数 doInBackground(Params)的输入参数
Progress:
后台任务执行的百分比, 他通过publicProgress(Progress)传给task执行过程中调用的函数onProgressUpdate(Progress)
Result:
当后台线程执行完后输出给UI线程的数据类型,它是task执行过程中调用的函数onPostExecute(Result)的输入参数
AsyncTask的执行分为四个步骤,每一步都对应一个回调方法,这些方法不应该由应用程序调用,开发者只需要按照需要重写这些方法。 根据下面这个例子, 讲下这四个步骤:

比如上图中应用预览区域显示的几张图需要从网络拉取, 我们想开始显示默认的图标, 然后依次从网络拉取图片, 拉取一张更新一张, 如果使用asyncTask来实现, 执行过程如下:
1. onPreExecute()
该方法将在执行实际的后台操作前被UI thread调用。可以在该方法中做一些准备工作,比如加载几张默认的预览图
2. doInBackground(Params...)
将在onPreExecute 方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台计算工作。比如从网络拉取预览图, 每拉取一张以后, 可以调用 publishProgress方法来更新一张默认的图片。
3. onProgressUpdate(Progress...)
在publishProgress方法被调用后,这个方法将被UI线程调用, 用于更新进度等界面显示。在上面那个例子中, 调用这个函数更新一张图片
4. onPostExecute(Result)
在doInBackground 执行完成后,onPostExecute 方法将被UI thread调用,后台的计算结果将通过该方法传递到UI thread.
为了正确的使用AsyncTask类,以下是几条必须遵守的准则:
1) Task的实例必须在UI thread中创建
2) execute方法必须在UI thread中调用
3) 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法
4) 该task只能被执行一次,否则多次调用时将会出现异常
doInBackground方法和onPostExecute的参数必须对应,这两个参数在AsyncTask声明的泛型参数列表中指定,第一个为doInBackground接受的参数,第二个为显示进度的参数,第第三个为doInBackground返回和onPostExecute传入的参数。
AsyncTask 的优势体现在:
•线程的开销较大,如果每个任务都要创建一个线程,那么应用程 序的效率要低很多;
•线程无法管理,匿名线程创建并启动后就不受程序的控制了,如果有很多个请求发送,那么就会启动非常多的线程,系统将不堪重负。
•另外,前面已经看到,在新线程中更新UI还必须要引入handler,这让代码看上去非常臃肿。
AsyncTask注意点:
在官方文档中指出, AsyncTasks should ideally be used for short operations, 就是说asyncTask执行的任务应该是一些短时间内可以完成的任务, 因为在android3.0之后, 默认情况下, 同一时间只能有一个asyncTask在运行, 也就是说所有的task都是串行运行的(AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.)所以如果某个task执行时间很长, 会导致后面的task长时间等待, 当然也可以通过调用executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR), 可以同时运行5个task, 具体用法可以参考:
http://blog.csdn.net/hitlion2008/article/details/7983449
下面举个AsyncTask使用demo:
class AppPreviewInitTask extends AsyncTask<String, Bitmap, Integer> {
private int mIndex = 0;
@Override
protected void onPreExecute() {
//加载显示默认的预览图
loadDefaultPreview();
}
@Override
protected Integer doInBackground(String... params) {
//从网络获取预览图
for (int i = 0; i < 5; ++i) {
mIndex = i;
Bitmap bitmap = getFromNet(params[0]);
//更新一张预览图
publishProgress(bitmap);
}
return null;
}
@Override
protected void onProgressUpdate(Bitmap... values) {
//index标记更新那张预览图
refreshPreview(mIndex, values[0]);
}
@Override
protected void onPostExecute(Integer result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
}
在更新预览图时发现总是会随机的漏掉几张(没有刷新), 开始以为
onProgressUpdate()执行有问题, 后来发现是mIndex的问题, 它在task中更新, 在UI线程中使用, 没有进行线程同步, 导致UI线程中使用mIndex时, 可能他已经发生变化了, 解决这个问题是自定义一个数据结构, 如下:
Private static class ImageInfo {
Public int mIndex = 0;
Public Bitmap mIcon;
}
这样的话, doInBackground()中调用publishProgress(ImageInfo info)时传入imageInfo类型的实参即可
AsyncTask使用详细说明的更多相关文章
- Android线程之AsyncTask
在之前的博客中为大家分享过关于Android多线程处理,想必大家对于Android为什么要使用多线程已经有了清晰的认识,我就在简单唠两句,Android规定UI界面的更新必须在在主线程进行,对于访问网 ...
- Android简易实战教程--第三十三话《 AsyncTask异步倒计时》
本篇小案例,完成一个倒计时.方式选择AsyncTask.代码贴在下面: 布局文件soeasy: <LinearLayout xmlns:android="http://schemas. ...
- Xamarin.Android 使用AsyncTask提示上传动态
我们有时候会通过WebServices上传数据,如果信息量过大并没有提示,用户会觉得是死机,或是系统崩溃,这时候我们可以用到AsyncTask(异步任务)来提示上传信息,例如:正在上传数据... 这里 ...
- 深入理解AsyncTask的工作原理
一.为什么需要工作者线程 我们知道,Android应用的主线程(UI 线程)肩负着绘制用户界面和及时响应用户操作的重任,为了避免“用户点击按钮后没反应”这样的糟糕用户体验,我们就要确保主线程时刻保持着 ...
- 【转】 Pro Android学习笔记(九二):AsyncTask(1):AsyncTask类
文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowingflying/ 在Handler的学习系列中,学习了如何h ...
- Android多线程分析之三:Handler,Looper的实现
Android多线程分析之三:Handler,Looper的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处 在前文<Android多 ...
- Android查缺补漏(线程篇)-- AsyncTask的使用及原理详细分析
本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8515304.html 一.AsyncTask的使用 AsyncTask是一种轻 ...
- android AsyncTask 详细例子
一个典型AsyncTask的. 01 public class DialogTestActivity extends Activity { 02 private Button button1; ...
- android AsyncTask 详细例子(2)
超时处理 001 import java.util.Timer; 002 import java.util.TimerTask; 003 004 import android.app.Activi ...
随机推荐
- Maven 打jar包,pom文件配置
以下是pom.xml文件的相关配置. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="h ...
- 利用InstallShiled 10.5制作AE应用程序安装包
[转]利用InstallShiled 10.5制作AE应用程序安装包 作者:3SNEWS 社区ESRI(ArcGIS)版版主:zhaoxiang_whuhttp://www.3snews.net/bb ...
- Eclipse js报错问题解决办法
最近在Eclipse中导入新项目后会发现js报错,但是不影响程序的运行,但是对于程序员的我们来说多少还是比较在意代码前面的红色的X的,有木有??? 上网也查了很多方法,对于其中一种方法表示不能完全解决 ...
- Hadoop streaming使用自定义python版本和第三方库
在使用Hadoop的过程中,遇到了自带python版本比较老的问题. 下面以python3.7为例,演示如何在hadoop上使用自定义的python版本以及第三方库. 1.在https://www.p ...
- OK335xS U-boot 环境变量解析
/************************************************************************************************** ...
- [LeetCode&Python] Problem 872. Leaf-Similar Trees
Consider all the leaves of a binary tree. From left to right order, the values of those leaves form ...
- linux中grep用法(“或”、“与”)
1.普通用法 grep keyword 若果keyword中有空格 grep "keyword" 例如: ls | grep mp4 2.“与”操作(其实就是多次筛选) grep ...
- ElasticSearch(五):简单的ElasticSearch搜索功能
这里主要是一些简单的ElasticSearch的搜索功能,复杂的搜索,比如过滤,聚合等以后单独在写 1. 搜索全部 GET book/_search 直接搜索全部,下面是对搜索结果的详细介绍:默认情况 ...
- UT源码_105032014033
需求描述: 设计佣金问题的程序 commission方法是用来计算销售佣金的需求,手机配件的销售商,手机配件有耳机(headphone).手机壳(Mobile phone shell).手机贴膜(Ce ...
- 【BZOJ2558】Count on a tree
又是因为傻逼错误浪费了半天时间 原题: 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个 ...