我们编程的时候经常需要处理同步任务和异步任务,在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. 【javascript】javascript中function(){},function(){}(),new function(){},new Function()

    和java比起来,javascript真的是松散的无以复加,不过这也让我们在无聊之余,有精力去探讨一些复杂的应用,从而在开发之路上,获得一些新的想法. javascript中的类的构造 javascr ...

  2. Runway for Mac(UML 流程图绘图工具)破解版安装

    1.软件简介    Runway 是 macOS 系统上一款强大实用的软件开发工具,Runway for Mac 是一个界面简单功能强大的UML设计师.此外,Runway for Mac 带给你所有你 ...

  3. 搭建自己的 github.io 博客

    1.前言 github.io 是基于 Github 的 repo 管理,这意味着咱们对其是有绝对的控制,这个跟放在第三方的平台比,可控性要好太多. 使用 github pages 服务搭建博客的好处有 ...

  4. 【Algorithm】自顶向下的归并排序

    一. 算法描述 自顶向下的归并排序:采用分治法进行自顶向下的程序设计方式,分治法的核心思想就是分解.求解.合并. 先将长度为N的无序序列分割平均分割为两段 然后分别对前半段进行归并排序.后半段进行归并 ...

  5. OpenCV 学习笔记 02 处理文件、摄像头和图形用户界面

    在处理文件前需要引入OpenCV库,同时也引入unmpy库 import cv2 import numpy as np 1 基本的读写操作 1.1 图像文件的读写操作 1.1.1 图像文件的读取操作 ...

  6. PostgreSQL基础命令

    1. 查看数字库和表 切换用户postgres su postgres 执行psql进入后台(就像执行mysql进入后台一样) 2. 更新postgres密码 \password 3. 创建数据库用户 ...

  7. 【转载】使用 Google Guava 美化你的 Java 代码

    转载地址: https://blog.csdn.net/wisgood/article/details/13297535 原文地址:https://my.oschina.net/leejun2005/ ...

  8. Linux vi/vim替换命令的使用说明[转]

    vi/vim 中可以使用 :s 命令来替换字符串.:s/vivian/sky/ 替换当前行第一个 vivian 为 sky:s/vivian/sky/g 替换当前行所有 vivian 为 sky:n, ...

  9. Logstash 报错 An unexpected error occurred! :error => bad URI(is not URI?,是因为路径c:\program files\logstash\logstash.bat 中有空格

    I am trying to run logstash under c:\program filesbut I get an error An unexpected error occurred! : ...

  10. csc.exe已退出,代码为-532462766

    我的surface pro4爆屏了 打电话给微软客服,那边说3,4天内给我回复 只能转移源码等资料到老电脑上,老电脑是神舟 精盾K480N I7D2,装的是WIN10预览版build 1625.rs2 ...