我们编程的时候经常需要处理同步任务和异步任务,在Android里面存在一个特性,就是UI线程是不安全的线程。所谓UI线程不安全也就是我们的主线程(进程启动的第一个线程)不能在线程外操作主线程的资源。因为主线程的资源没有做同步处理。也就是我们一般说的线程同步问题。

  我们做Android应用的时候,进程需要在一个子线程执行一些耗时的操作,例如下载、播放等。这种情况我们一般使用Handler和线程结合处理,子线程负责处理耗时操作,然后通知Handler处理UI更新。Handler和子线程结合处理适合对精度控制要求比较高或者任务耗时比较长或者比较反复的情况。除了Handler和线程结合使用,Android也为我们提供了另外一种选择,也就是今天要说的AsyncTask。

  AsyncTask内部也是使用了Handler和线程的模式,只是Google把它封装好了。下面我们看看AsyncTask如何使用。

 (PS:新建的QQ群,有兴趣可以加入一起讨论:Android群:322599434)

1、android.os.AsyncTask的定义

public abstract class AsyncTask<Params, Progress, Result> 
  • Params:输入的参数
  • Progress:更新的进度,一般用来更新UI的进度信息
  • Result:是执行后的返回结果

这些参数都是泛型定义,所以我们可以定义自己的数据类型作为参数,另外如果不需要相关传输,可以传入Void即可。

2、AsyncTask接口

//执行异步任务,启动异步任务需要执行这个接口
public final AsyncTask<Params, Progress, Result> execute(Params... params)
{
return executeOnExecutor(sDefaultExecutor, params);
}
//在execute()被调用后立即执行,可以做一些任务初始化
protected void onPreExecute()
{
}
//在onPreExecute()执行后执行,执行一些耗时操作,此方法将接收输入参数和返回计算结果。
//在执行过程中可以调用publishProgress()来更新进度信息
protected abstract Result doInBackground(Params... params);
//在调用publishProgress(Progress... values)时,回调这个方法,用来更新进度信息
protected void onProgressUpdate(Progress... values)
{
}
//doInBackground执行完后,会回调此方法,用于更新界面信息
protected void onPostExecute(Result result)
{
}

  上面是AsyncTask的一些重要接口和方法,可以看出大部分都是空方法还有就是虚函数。我们继承AsyncTask的时候,一般都需要重写上面的方法,方便我们执行相应的操作。

3、AsyncTask例子

下面是我编写的一个使用AsyncTask下载图片的例子,这个例子功能是利用AsyncTask下载一张图片。

    private class DownLoad extends AsyncTask<String, Integer, String>
{
//onPreExecute方法在execute()后执行
@Override
protected void onPreExecute()
{
Log.i(TAG, "onPreExecute() enter");
mShowLogTextView.setText("onPreExecute。。。begin downLoad");
} //doInBackground方法内部执行后台任务,不能在里面更新UI,否则有异常。
@Override
protected String doInBackground(String... params)
{
Log.i(TAG, "doInBackground(String... params) enter"); URL imageUrl=null;
try
{
imageUrl=new URL(params[]);
}
catch (MalformedURLException e)
{
e.printStackTrace();
Log.e(TAG, e.getMessage());
}
try
{
//使用HttpURLConnection打开连接
HttpURLConnection urlConn=(HttpURLConnection)imageUrl.openConnection();
urlConn.setDoInput(true);
urlConn.connect();
//将得到的数据转化成InputStream
InputStream is=urlConn.getInputStream();
//将InputStream转换成Bitmap
mDownLoadBtBitmap=BitmapFactory.decodeStream(is);
is.close();
//不能在这里更新UI,否则有异常******
//mNetImageView.setImageBitmap(bitmap);

}catch(IOException e)
{
Log.e(TAG,e.getMessage());
} return "ok";
} //onProgressUpdate方法用于更新进度信息
@Override
protected void onProgressUpdate(Integer... progresses)
{
Log.i(TAG, "onProgressUpdate(Integer... progresses) enter"); mShowLogTextView.setText("onProgressUpdate Downloading...");
} //onPostExecute用于doInBackground执行完后,更新界面UI。
//result是doInBackground返回的结果

@Override
protected void onPostExecute(String result)
{
Log.i(TAG, "onPostExecute(Result result) called");
mShowLogTextView.setText("Down load finish result="+result); mNetImageView.setImageBitmap(mDownLoadBtBitmap);
} //onCancelled方法用于取消Task执行,更新UI
@Override
protected void onCancelled()
{
Log.i(TAG, "onCancelled() called");
mShowLogTextView.setText("onCancelled");
}
}

  上面是继承了AsyncTask类,重写了里面相关方法的之类,从上面可以看出AsyncTask主要的操作任务都是放到了doInBackground执行。然后onPostExecute最后更新结果。让AsyncTask开始执行 的方法很简单,只要调用execute并传入相关参数即可。

public void onClick(View v)
{
if (v==mPlayMusicButton)
{
//传入下载图片的地址 mythou
mDownLoad.execute("http://pic.desk.chinaz.com/file/10.11.10/7/jillxs40.jpg");
//mDownLoad.execute("http://www.baidu.com/img/bdlogo.gif");
}
}

  这里传入的参数是作为doInBackground方法的参数,这里传入图片的URL,然后执行下载图片操作。下面说说AsyncTask使用的时候需要注意的事情。

  • AsyncTask的实例必须在UI线程中创建,并且在UI线程调用execute(Params... params)开始任务。
  • 不要手动调用onPreExecute(),doInBackground(Params... params),onProgressUpdate(Progress... values),  onPostExecute(Result result)等AsyncTask的回调函数。
  • 不能在doInBackground(Params... params)中更改UI组件的信息。
  • 一个任务实例只能执行一次,如果执行第二次将会抛出异常。

下面是这个例子执行效果:

AsyncTask的Demo代码下载:点击这里

Edited by mythou

原创博文,转载请标明出处:http://www.cnblogs.com/mythou/p/3191174.html 

Android 异步任务——AsyncTask (附使用AsyncTask下载图片Demo)的更多相关文章

  1. android+nutz后台如何上传和下载图片

    android+nutz后台如何上传和下载图片  发布于 588天前  作者 yummy222  428 次浏览  复制  上一个帖子  下一个帖子  标签: 无 最近在做一个基于android的ap ...

  2. Android异步处理二:使用AsyncTask异步更新UI界面

    在<Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面>中,我们使用Thread+Handler的方式实现了异步更新UI界面,这一篇中,我们介绍一种更为简 ...

  3. Python爬虫获取异步加载站点pexels并下载图片(Python爬虫实战3)

    1. 异步加载爬虫 对于静态页面爬虫很容易获取到站点的数据内容,然而静态页面需要全量加载站点的所有数据,对于网站的访问和带宽是巨大的挑战,对于高并发和大访问访问量的站点来说,需要使用AJAX相关的技术 ...

  4. 将QT开发的界面程序封装成DLL,在VC中成功调用(必须有消息循环,所以使用了QTWinmigrate,附CSDN可下载的Demo)

    最近手头的一个项目需要做一个QT界面,并且封装成DLL,然后再动态调用DLL给出的接口函数,使封装在DLL内部的QT界面跑起来,在网上查了很多资料,今天终于成功了,经验不敢独享,因为CSDN给了我很多 ...

  5. 【转】COCOS2D-X之CCHttpRequest下载图片Demo

    #include "pthread.h" #pragma comment(lib,"libcurl_imp.lib") #pragma comment(lib, ...

  6. Android异步处理系列文章四篇之四 AsyncTask的实现原理

    Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面Android异步处理二:使用AsyncTask异步更新UI界面Android异步处理三:Handler+Loope ...

  7. Android异步处理系列文章四篇之二 使用AsyncTask异步更新UI界面

    Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面Android异步处理二:使用AsyncTask异步更新UI界面Android异步处理三:Handler+Loope ...

  8. Android异步处理四:AsyncTask的实现原理

    在<Android异步处理二:使用AsyncTask异步更新UI界面>一文中,我们介绍了如何使用AsyncTask实现异步下载图片,并且更新图片到UI界面的方法.本篇我们将学习Framew ...

  9. 【转载】Android异步处理系列文章

    本博文地址:http://blog.csdn.net/mylzc/article/details/6777767 转载请注明出处. 为了给用户带来良好的交互体验,在Android应用的开发过程中需要把 ...

随机推荐

  1. 【SqlServer】如何把本地SqlServer数据库部署到远程服务器上

    这里笔者使用的使用SqlServer2012,本机和远程环境均为Win7. 1.选中需要部署的数据库,右击>任务>分离.选中删除连接. 2.现在在左侧的表中就看不见刚才那个数据了. 3.在 ...

  2. Eclipse中创建Maven多模块工程

    1.先创建父项目 在Eclipse里面New -> Maven Project: 在弹出界面中选择“Create a simple project” 这样,我们就按常规模版创建了一个Maven工 ...

  3. aaronyang的百度地图API之LBS云与.NET开发 Javascript API 2.0【基本地图的操作】

    为了更简单的演示,我们创建个.NET的ASP.NET MVC4项目 好了,上面都是后话,POI说白了,就是你的用户的数据,很多数据,不过没关系,因为你的数据如果存在百度的LBS云上,那么大数据你就不用 ...

  4. 恢复Ext3下被删除的文件

    下面是这个教程将教你如何在Ext3的文件系统中恢复被rm掉的文件. 假设我们有一个文件名叫 ‘test.txt’  $ls -il test.txt 15 -rw-rw-r– 2 root root ...

  5. UnicodeDecodeError: 'utf-8' codec can't decode byte

    for line in open('u.item'): #read each line whenever I run this code it gives the following error: U ...

  6. python标准库介绍——34 commands 模块详解

    ==commands 模块== (只用于 Unix) ``commands`` 模块包含一些用于执行外部命令的函数. [Example 3-7 #eg-3-7] 展示了这个模块. ====Exampl ...

  7. VB通用数据库操作方法

    1.VB通用数据操作方法. 2.通用数据库查询方法. 3.通用数据库操作方法. 'ERP查询数据库 Public Function YZQuery(sqls As String, msgstring ...

  8. U811.1接口EAI系列之四--委外订单生成--VB语言

    委外订单主细表.子个构成需求.具体代码与参数说明. 下面调用的通用方法在: http://www.cnblogs.com/spring_wang/p/3393147.html 作者:王春天 2013- ...

  9. marquee标签详解

    <marquee>标签,它是成对出现的标签,首标签<marquee>和尾标签</marquee>之间的内容就是滚动内容.<marquee>标签的属性主要 ...

  10. 不要随便使用 runAllManagedModulesForAllRequests="true" 来解决问题

    在 IIS 7.0 中,对于使用 Url 路由 访问页面的 ASP.NET 应用程序,IIS可能会不能出 Url 是对 ASP.NET 的请求. 会显示404啊,403啊之类的错误代码(因为路径不存在 ...