---恢复内容开始---

因为android的UI线程是不安全的,如果你UI线程里执行一些耗时任务,很容易就导致程序崩溃。并且目前网络任务也不能够在UI线程里执行。处理这些问题除了直接写一个线程以外,Android还提供一个AsyncTask(异步任务类)来更简单的处理一些耗时任务。

AsyncTask<>是一个抽象类,通常用于继承,继承时需要指定三个泛型参数。

1、Params:启动任务时传入的参数的类型。这是一个数组,可以传多个参数。调用时使用params[0]、params[1]、params[2]来获取。

2、Progress:后台任务完成的进度值的类型。

3、Result:后台任务执行完毕返回结果的类型。

使用AsyncTask需要如下三步:

1、继承抽象类,实现一个子类,传入三个泛型参数。如果有参数不需要使用可设为Void。

2、根据需要,可实现以下方法。

  • doInBackground(Params...):该方法是必须的,这个方法下写的是后台线程要执行的任务,并且会在子线程运行(其他方法都是在UI线程执行)。。该方法可以调用publicProgress(Progress...values)方法更新任务的进度。
  • onProgressUpdate(Progress... values):该方法在上一步调用publicProgress时触发。
  • onPreExecute():该方法会在执行doInBackground方法前执行,用于做一些准备工作。
  • onPostExecute(Result result):当doInBackground执行结束之后,系统会自动调用该方法,返回值也会传到此函数。我们可以在这里完成后台线程执行后的结果。

3、最后用新建我们继承类后的结果,然后调用execute(Params... params)。

  注意:对象必须在UI线程中创建、execute方法必须在UI线程中调用、以上四个方法都需系统自动调用、每个对象只能被执行一次,多次调用引发异常。

实例

讲了那么多铺垫,让我们来讲个例子吧~

我现在想从互联网上下载一张图片,就使用这个AsyncTask来做一下吧~

为让所有方法都实现一次,我们用两种方法实现:1、下载完毕后直接进行显示。2、一边加载一边显示进度,加载完毕显示图片。

下面是第一种的代码,相对简单一点,只用了两个函数。

public class MainActivity extends Activity {

    int downloadSize;
int fileSize; Button bn;
ImageView iv;
ProgressBar progressBar;
String url = "http://ww1.sinaimg.cn/mw690/6aa88161gw1eqqbw7h821j20hs0hsaba.jpg"; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); bn = (Button) findViewById(R.id.down);
iv = (ImageView) findViewById(R.id.image); MyOnClickListener myOnClickListener = new MyOnClickListener();
bn.setOnClickListener(myOnClickListener);
} class MyOnClickListener implements android.view.View.OnClickListener{ @Override
public void onClick(View v) { AsyncDownload asyncDownload = new AsyncDownload();
asyncDownload.execute(url);
}
} class AsyncDownload extends AsyncTask<String, Integer, Bitmap>
{ @Override
protected Bitmap doInBackground(String... params) { String imageUrl = params[0]; URL url;
try {
url = new URL(imageUrl);
InputStream is = url.openStream();
BitmapFactory.Options op = new BitmapFactory.Options();
op.inSampleSize = 2;
Bitmap bitmap = BitmapFactory.decodeStream(is, null,
op); } catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
} @Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result); iv.setImageBitmap(result);
}
  }
}

上面的代码的功能是点击按钮,然后doInBackground后台下载图片,下载完毕onPostExecute显示图片。仅仅使用了两个函数,但是实现了AsyncTask的核心功能。

然后让我们感受一下能够显示进度的。

public class MainActivity extends Activity {

    int downloadSize;
int fileSize; Button bn;
ImageView iv;
ProgressBar progressBar;
String url = "http://ww1.sinaimg.cn/mw690/6aa88161gw1eqqbw7h821j20hs0hsaba.jpg"; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); bn = (Button) findViewById(R.id.down);
iv = (ImageView) findViewById(R.id.image);
progressBar = (ProgressBar) findViewById(R.id.bar); MyOnClickListener myOnClickListener = new MyOnClickListener();
bn.setOnClickListener(myOnClickListener);
} Handler handler = new Handler(){ public void handleMessage(android.os.Message msg)
{ }
}; class MyOnClickListener implements android.view.View.OnClickListener{ @Override
public void onClick(View v) { AsyncDownload asyncDownload = new AsyncDownload();
asyncDownload.execute(url);
}
} class AsyncDownload extends AsyncTask<String, Integer, Void>
{ @Override
protected Void doInBackground(String... params) { String imageUrl = params[0]; try {
URL url = new URL(imageUrl);
URLConnection conn = url.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
fileSize = conn.getContentLength(); publishProgress(0x111); FileOutputStream fos = new FileOutputStream(getPath());
byte[] bytes = new byte[1024];
int len = -1;
while((len = is.read(bytes))!=-1)
{
fos.write(bytes, 0, len);
downloadSize+=len;
publishProgress(0x222);
}
publishProgress(0x333);
is.close();
fos.close();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
} @Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values); switch(values[0])
{
case 0x111:
progressBar.setMax(fileSize);
break;
case 0x222:
progressBar.setProgress(downloadSize);
break;
case 0x333:
try {
if(getPath().endsWith(".jpg")||getPath().endsWith(".png")){
FileInputStream fis = new FileInputStream(getPath());
iv.setImageBitmap(BitmapFactory.decodeStream(fis));
}
downloadSize = 0;
fileSize = 0;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
} public String getPath() {
File root = getExternalCacheDir();
if (root != null)
{
return root.getAbsolutePath() + "test.jpg";
} return null;
}
}

这里实现的功能是点击下载按钮,后台从互联网加载文件,首先获取文件大小,设置progressbar最大值,然后一边下载、一边存入本地、一边设置progressbar的值,实现进度条。下载完毕从本地获取图片显示出来。这一次多使用了显示进度的函数onProgressUpdate。

其实,onProgressUpdate这个函数一般我们在线程里会用Handler来实现。

在AsyncTask给我们把平常使用线程进行异步操作的所用东西打包在一起了,不得不说确实省了一些事。

实际上能够用AsyncTask实现的东西完全可以直接用线程来实现~

我在些第二个代码的时候写顺了手,用Handler实现了一遍,大家在下面可以看一下。

public class MainActivity extends Activity {

    int downloadSize;
int fileSize; Button bn;
ImageView iv;
ProgressBar progressBar;
String url = "http://ww1.sinaimg.cn/mw690/6aa88161gw1eqqbw7h821j20hs0hsaba.jpg"; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); bn = (Button) findViewById(R.id.down);
iv = (ImageView) findViewById(R.id.image);
progressBar = (ProgressBar) findViewById(R.id.bar); MyOnClickListener myOnClickListener = new MyOnClickListener();
bn.setOnClickListener(myOnClickListener);
} Handler handler = new Handler(){ public void handleMessage(android.os.Message msg)
{
switch(msg.what)
{
case 0x111:
progressBar.setMax(fileSize);
break;
case 0x222:
progressBar.setProgress(downloadSize);
break;
case 0x333:
try {
if(getPath().endsWith(".jpg")||getPath().endsWith(".png")){
FileInputStream fis = new FileInputStream(getPath());
iv.setImageBitmap(BitmapFactory.decodeStream(fis));
}
downloadSize = 0;
fileSize = 0;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
}; class MyOnClickListener implements android.view.View.OnClickListener{ @Override
public void onClick(View v) { AsyncDownload asyncDownload = new AsyncDownload();
asyncDownload.execute(url);
}
} class AsyncDownload extends AsyncTask<String, Integer, Void>
{ @Override
protected Void doInBackground(String... params) { String imageUrl = params[0]; try {
URL url = new URL(imageUrl);
URLConnection conn = url.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
fileSize = conn.getContentLength(); handler.sendEmptyMessage(0x111); FileOutputStream fos = new FileOutputStream(getPath());
byte[] bytes = new byte[1024];
int len = -1;
while((len = is.read(bytes))!=-1)
{
fos.write(bytes, 0, len);
downloadSize+=len;
handler.sendEmptyMessage(0x222);
}
handler.sendEmptyMessage(0x333);
is.close();
fos.close();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
} public String getPath() {
File root = getExternalCacheDir();
if (root != null)
{
return root.getAbsolutePath() + "test.jpg";
} return null;
}
}

啦啦啦,就到这里吧~

Android AsyncTask分析的更多相关文章

  1. Android AsyncTask 分析内部实现

    sdk3.0前,使用内部的线程池,多线程并发运行.线程池大小等于5,最大达128 sdk3.0后,使用默认的serial线程池.运行完一个线程,再顺序运行下一个线程.sdk3.0<=curren ...

  2. Android多线程分析之五:使用AsyncTask异步下载图像

    Android多线程分析之五:使用AsyncTask异步下载图像 罗朝辉 (http://www.cnblogs.com/kesalin) CC 许可,转载请注明出处 在本系列文章的第一篇<An ...

  3. Android多线程分析之四:MessageQueue的实现

    Android多线程分析之四:MessageQueue的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处 在前面两篇文章<Androi ...

  4. Android多线程分析之三:Handler,Looper的实现

    Android多线程分析之三:Handler,Looper的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处 在前文<Android多 ...

  5. Android多线程分析之二:Thread的实现

    Android多线程分析之二:Thread的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处   在前文<Android多线程分析之一 ...

  6. Android多线程分析之一:使用Thread异步下载图像

    Android多线程分析之一:使用Thread异步下载图像 罗朝辉 (http://www.cnblogs.com/kesalin) CC 许可,转载请注明出处   打算整理一下对 Android F ...

  7. android AsyncTask介绍(转)

    android AsyncTask介绍 AsyncTask和Handler对比 1 ) AsyncTask实现的原理,和适用的优缺点 AsyncTask,是android提供的轻量级的异步类,可以直接 ...

  8. Android Launcher分析和修改13——实现Launcher编辑模式(1) 壁纸更换

    已经很久没更新Launcher系列文章,今天不分析源码,讲讲如何在Launcher里面添加桌面设置的功能.目前很多第三方Launcher或者定制Rom都有简单易用的桌面设置功能.例如小米MIUI的La ...

  9. Android Launcher分析和修改9——Launcher启动APP流程

    本来想分析AppsCustomizePagedView类,不过今天突然接到一个临时任务.客户反馈说机器界面的图标很难点击启动程序,经常点击了没有反应,Boss说要优先解决这问题.没办法,只能看看是怎么 ...

随机推荐

  1. SQL UNION 和 UNION ALL 操作符\SQL SELECT INTO 语句\SQL CREATE DATABASE 语句

    SQL UNION 操作符 UNION 操作符用于合并两个或多个 SELECT 语句的结果集. 请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列.列也必须拥有相似的数据类型.同时,每 ...

  2. SSR———团队作业:小型论坛的设计与初步实现

    小型论坛的设计与初步实现 这次团队作业,我们设计的是一个小型论坛,作为团队中的一员,我主要负责对用户进行需求调研与对用户体验的过程拍摄总结,力求我们的项目在力所能及的范围内更加完美 视频:   度盘链 ...

  3. GPS部标平台的架构设计(九)-GPS监控客户端设计

    交通部的部标过检,所有的测试都是从客户端发起的,也是在客户端体现的,在客户端承载了部标标准所要求的所有的功能,是整个部标平台当中工作量最大的部分,也是最繁琐的部分. 客户端设计面临两个问题: 1.基于 ...

  4. Thinkphp3.2----------------Thinkphp3.2的目录结构介绍

    ThinkPHP框架目录结构\index.php         入口文件\Application     应用目录\Public         资源文件目录\ThinkPHP         框架 ...

  5. python web前端

    概述 HTML是英文Hyper Text Mark-up Language(超文本标记语言)的缩写,他是一种制作万维网页面标准语言(标记).相当于定义统一的一套规则,大家都来遵守他,这样就可以让浏览器 ...

  6. eclipse中Maven创建WEB项目

    刚刚学到Maven的时候总是容易忽视到一些创建Maven项目是的步骤, 这里记录笔者熟悉一种,直接创建Maven Project 下面开始吧--- 选择web-app,没得说,然后那些groupID ...

  7. Android中ListView动态加载数据

    1. 引言: 为了提高ListView的效率和应用程序的性能,在Android应用程序中不应该一次性加载ListView所要显示的全部信息,而是采取分批加载策略,随着用户的滑动,动态的从后台加载所需的 ...

  8. 对jquery分页的升级

    以前写的分页用了好久了,但是分页时除了传页面外有时还要传一些其它参数,以前操作时要把传的参数放到隐藏hidden中,分页时在取出来,这样比较麻烦,今天无事,重新包装了一下 直接上代码吧 css用了bo ...

  9. ssh免密码认证

    举例:有机器PC_A(172.0.246),PC_B(172.0.1.140).现想A通过ssh免密码登录到B. 1.在PC_A主机下生成公钥/私钥对 [comodo@PC_A ~]$ ssh-key ...

  10. 07_编写天气预报和手机归属地的WebService

    <s:element ref="s:schema" /> <s:any /> <s:any minOccurs="2" maxOc ...