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类型的实参即可

时间: 2024-10-06 00:40:12

AsyncTask使用详细说明的相关文章

Android线程之AsyncTask

在之前的博客中为大家分享过关于Android多线程处理,想必大家对于Android为什么要使用多线程已经有了清晰的认识,我就在简单唠两句,Android规定UI界面的更新必须在在主线程进行,对于访问网络的耗时操作必须在子线程中执行,所以如果你想成为一名真正的Android开发工程师,多线程是你的必修课.本篇带给大家关于Android为我们封装好的一个简单的线程类AsyncTask. AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提

深入理解AsyncTask的工作原理

一.为什么需要工作者线程 我们知道,Android应用的主线程(UI 线程)肩负着绘制用户界面和及时响应用户操作的重任,为了避免“用户点击按钮后没反应”这样的糟糕用户体验,我们就要确保主线程时刻保持着较高的响应性.为了做到这一点,我们就要把耗时的任务移出主线程,那么耗时的任务交给谁来完成呢?答案就是工作者线程.Android开发中我们通常让主线程负责前台用户界面的绘制以及响应用户的操作,让工作者线程在后台执行一些比较耗时的任务.Android中的工作者线程主要有AsyncTask.IntentS

Android中多线程编程(四)AsyncTask类的详细解释(附源码)

Android中多线程编程中AsyncTask类的详细解释 1.Android单线程模型 2.耗时操作放在非主线程中执行 Android主线程和子线程之间的通信封装类:AsyncTask类 1.子线程中更新UI 2.封装.简化异步操作. 3.AsyncTask机制:底层是通过线程池来工作的,当一个线程没有执行完毕,后边的线程是无法执行的.必须等前边的线程执行完毕后,后边的线程才能执行. AsyncTask类使用注意事项: 1.在UI线程中创建AsyncTask的实例 2.必须在UI线程中调用As

Android AsyncTask 详细解析

结构 继承关系 public abstract class AsyncTask extends Object java.lang.Object android.os.AsyncTask<Params, Progress, Result> 类概述 AsyncTask能够适当地.简单地用于 UI线程. 这个类不需要操作线程(Thread)就可以完成后台操作将结果返回UI. 异步任务的定义是一个在后台线程上运行,其结果是在 UI线程上发布的计算. 异步任务被定义成三种泛型类型: Params,Pro

AsyncTask中各个函数详细的调用过程,初步实现异步任务

异步任务是我们经常要使用的东西,android中提供了一套解决方案,从异步任务的开始到结束,相当完善.本实例没有任何应用价值,只是说明了AsyncTask中各个函数的调用顺序. 具体的结果看下面的Log输出即可: 异步任务类: AsyncTaskTest.java package com.kale.asynctask; import java.net.URL; import android.R.integer; import android.os.AsyncTask; /** * @author

Android查缺补漏(线程篇)-- AsyncTask的使用及原理详细分析

本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8515304.html 一.AsyncTask的使用 AsyncTask是一种轻量级的异步任务类,可以很方便的在线程池中执行异步任务,并且将进度和结果传递给主线程.其底层由Thread+handler实现. AsyncTask是一个抽象的泛型类,其类的声明如下: public abstract class AsyncTask<Params, Progress, Result>

Android应用开发-小巫CSDN博客客户端之显示博文详细内容

Android应用开发-小巫CSDN博客客户端之显示博文详细内容 上篇博文给大家介绍的是如何嵌入有米广告并且获取收益,本篇博客打算讲讲关于如何在一个ListView里显示博文的详细信息,这个可能是童鞋们比较困惑的,因为一篇博客可能有标题.摘要.图片.代码等等元素组成,我们要怎么在一个界面中显示这些内容并且按照自己的指定的方式显示呢,别急,下面会告诉大家. 重新整理一下一篇博文可能有以下元素: 标题 摘要 文本内容 图片 粗标题 代码块 在UI篇小巫已经介绍了,博文详细内容的主要控件就是一个Lis

Android-多线程AsyncTask

http://www.cnblogs.com/plokmju/p/android_AsyncTask.html AsyncTask,异步任务,可以简单进行异步操作,并把执行结果发布到UI主线程.AsyncTask是一个抽象类,它的内部其实也是结合了Thread和Handler来实现异步线程操作,但是它形成了一个通用线程框架,更清晰简单.AsyncTask应该被用于比较简短的操作(最多几秒钟).如果需要保持长时间运行的线程,可以使用ThreadPooExecutor或者FutureTask 首先来

异步任务AsyncTask使用解析

在Android中实现异步任务机制有两种方式,Handler和AsyncTask. Handler模式需要为每一个任务创建一个新的线程,任务完成后通过Handler实例向UI线程发送消息,完成界面的更新,这种方式对于整个过程的控制比较精细,但也是有缺点的,例如代码相对臃肿,在多个任务同时执行时,不易对线程进行精确的控制.关于Handler的相关知识,前面也有所介绍,不清楚的朋友们可以参照一下. 为了简化操作,Android1.5提供了工具类android.os.AsyncTask,它使创建异步任