在上一篇,详细介绍了AsynTask的基础知识。没有读过的朋友可以点击下面的链接:

http://www.cnblogs.com/fuly550871915/p/4892310.html

那么在这篇文章中,将编写实际的小例子,让大家看看,到底AsynTask是如何使用的。废话不多说了,例子很简单,请往下看。

一、一个异步加载网络图片的小例子

现在就跟着我一起来用AsynTask实现一个加载一张网络图片的小例子吧。首先我们看看我们要加载的这张图片是什么样的,如下:

这是我从网络张找的一张图片,它的地址是http://android-artworks.25pp.com/fs01/2015/01/05/4/110_416b936f41cb2b73dce64cbaf6bf1e16.png

下面我们就开始写代码吧。新建一个项目,别忘记给这个项目加上网络权限。然后修改它的activity_main.xml,代码如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
> <ImageView
android:id="@+id/img_url"
android:layout_width="200dp"
android:layout_height="200dp" /> <ProgressBar
android:id="@+id/progressbar"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_gravity="center"
/> </LinearLayout>

代码很简单,就是放置了一个ImageView用来放我们的这张网络图片的,然后再在中间放置一个进度条,用来显示进程。然后修改MainActivity的代码,如下:

 package com.example.asynctasktest;

 import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL; import org.apache.http.HttpConnection; import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory; public class MainActivity extends Activity { private ImageView img;
private ProgressBar progressBar;
private Bitmap bmp;
private static final String surl =" http://android-artworks.25pp.com/fs01/2015/01/05/4/110_416b936f41cb2b73dce64cbaf6bf1e16.png";
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); img = (ImageView) findViewById(R.id.img_url);
progressBar = (ProgressBar) findViewById(R.id.progressbar);
MyAsyncTask mTask = new MyAsyncTask();
mTask.execute(surl); } class MyAsyncTask extends AsyncTask<String, Void, Bitmap>{ protected Bitmap doInBackground(String... params) { String surl = params[0];
HttpURLConnection connection = null; try {
URL url = new URL(surl);//将字符串转化为网址对象
connection = (HttpURLConnection) url.openConnection();//创建网络接口
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
InputStream in = connection.getInputStream();//获取返回的数据流
bmp = BitmapFactory.decodeStream(in);//获取图片
in.close(); } catch (Exception e) { e.printStackTrace();
} return bmp;
} @Override
protected void onPreExecute() {
super.onPreExecute();
//显示进度条
progressBar.setVisibility(View.VISIBLE);
} @Override
protected void onPostExecute(Bitmap result) {
try {
Thread.sleep(5000);//为了观看效果,休眠5秒
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//关闭进度条和更新UI
progressBar.setVisibility(View.GONE);
img.setImageBitmap(bmp);
super.onPostExecute(result);
} } }

代码也很简单,在这里就用到了AsynTask来异步加载这张图片。doInBackground用来获取到这张图片并转化为Bitmap对象,然后再在onPostExecute方法中更新UI即可。好了,运行程序吧。效果图如下:

                            

通过这个例子,是不是对怎么使用AsyncTask更加熟悉了呢?那么下面我们再来写一个例子吧,这次用来模拟一个进度条。

二、一个模拟进度条的小例子

使用的当然就是AsyncTask中的publishProgress和onProgressUpdate方法了。代码其实很简单,直接看吧。新建一个项目,修改它的activity_main.xml代码,如下:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"> <Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="btnProgress"
android:text="按钮"/> </LinearLayout>

先设置一个按钮是为了触发进度条的。然后再编写progressbar.xml,里面放置一个横向的进度条即可。代码如下:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"> <ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" /> </LinearLayout>

新建活动,用来显示这个进度条,在这个类里面我们就使用AsyncTask让进度条动起来。

 package com.example.asynctasktest;

 import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.ProgressBar; public class ProgressbarActivity extends Activity {
private ProgressBar progressBar; protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.progressbar);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
MyAsyncTask mTask = new MyAsyncTask();
mTask.execute(); } //Integer就是制定进度的衡量单位类型
class MyAsyncTask extends AsyncTask<Void, Integer, Void>{ protected Void doInBackground(Void... params) {
for(int i=0;i<100;i++){
//传递任务执行的当前值
publishProgress(i);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
} //根据任务执行情况更新UI,其实就是更新进度条
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
progressBar.setProgress(values[0]);
} }
}

在这个活动中,我们在doInBackground中建立一个循环,然后将循环的值通过publishProgress方法传递给onProgressUpdate方法,用来更新进度条。这样子就到了模拟进度条的效果。

不要忘记给这个活动注册哈。然后修改MainAcitivity中的代码,添加按钮的点击事件。如下:

 package com.example.asynctasktest;

 import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.ProgressBar;
import android.app.Activity;
import android.content.Intent; public class MainActivity extends Activity { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
} public void btnProgress(View v){
Intent intent = new Intent(this,ProgressbarActivity.class);
startActivity(intent);
} }

下面我们运行程序,然后点击按钮,就会有下面的效果,如下:

三、AsyncTask的取消

我们以上面的进度条为例子,当进度更新到下面的情况时

我们返回到按钮界面,然后点击按钮,此时重新进入到进度条界面,如下:

而且等待了好久,才发现进度条才有开始启动,才又动起来。那这是为什么呢?这是因为我们之前的doInBackground里的线程还在进行,循环还在继续,所以AsyncTask还在执行。因此此刻重新进入进度条界面,就不可能立刻启动新的AsyncTask,而旧的呢又因为之前我们返回到按钮界面就没法重新绘制了。所以只有等旧的AsyncTask执行完毕,才会开启新的。因此你等了好久才,进度条才又重新运转起来。

其实解决这个问题,很简单,我们让AsyncTask的生命周期跟活动的生命周期一样就可以了,即在适当的时候取消AsyncTask即可。那么我们就修改一下代码,如下:

 package com.example.asynctasktest;

 import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.ProgressBar; public class ProgressbarActivity extends Activity {
private ProgressBar progressBar;
private MyAsyncTask mTask; protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.progressbar);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
mTask = new MyAsyncTask();
mTask.execute(); } //当跳到另外一个活动的时候调用该方法
protected void onPause() {
23 //如果mTask不为空,且正在运行
24 if(mTask !=null && mTask.getStatus() == AsyncTask.Status.RUNNING){
25 mTask.cancel(true);//取消该任务
26 }
27 super.onPause();
28 } //Integer就是制定进度的衡量单位类型
class MyAsyncTask extends AsyncTask<Void, Integer, Void>{ protected Void doInBackground(Void... params) {
for(int i=0;i<100;i++){
//传递任务执行的当前值
publishProgress(i);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
} //根据任务执行情况更新UI,其实就是更新进度条
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
progressBar.setProgress(values[0]);
} }
}

红色部分是我修改的代码,当活动跳转的时候,就取消掉当前正在执行的AsyncTask。然后重新运行程序,然后当进度条启动之后几秒钟,返回到按钮界面,然后再点击按钮。按照我们的逻辑,此时应该是进度条重新启动,但是呢?我就不贴效果图了,跟上面的两张图一样。如果你做了这个实验,你就会发现,根本没什么改变。那是为什么啊??我们明明已经取消了该任务啊!!

其实原因就是因为AsyncTask的cancel方法,只是将一个AsyncTask对象标记为待取消状态,当它的进程执行完毕才会真的去取消它。所以我们在上面的代码中即使用了这个方法,也没有用。

因此要想立刻取消AsyncTask任务,必须手动取消。即在进程中,我们时刻检查AsyncTask的状态是否为取消的状态,如果是,立刻人为终止线程即可。再修改代码,如下:

 package com.example.asynctasktest;

 import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.ProgressBar; public class ProgressbarActivity extends Activity {
private ProgressBar progressBar;
private MyAsyncTask mTask; protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.progressbar);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
mTask = new MyAsyncTask();
mTask.execute(); } //当跳到另外一个活动的时候调用该方法
protected void onPause() {
//如果mTask不为空,且正在运行
if(mTask !=null && mTask.getStatus() == AsyncTask.Status.RUNNING){
mTask.cancel(true);//取消该任务
}
super.onPause();
} //Integer就是制定进度的衡量单位类型
class MyAsyncTask extends AsyncTask<Void, Integer, Void>{ protected Void doInBackground(Void... params) {
for(int i=0;i<100;i++){
if(isCancelled()){//如果为取消状态,立刻break,跳出循环
break;
}
//传递任务执行的当前值
publishProgress(i); try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
} //根据任务执行情况更新UI,其实就是更新进度条
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
if(isCancelled()){
return;//如果为 取消状态,就立刻跳出
}
progressBar.setProgress(values[0]);
} }
}

红色地方是我修改的地方,在线程里面合适的地方我们判断当前的AsyncTask任务是不是取消状态,如果是就立刻跳出线程。然后再运行程序,按照上面的流程走一遍。我们发现一切正确了。无论什么情况,只要点击按钮进去,进度条就会立刻重新启动。效果图我就不贴了。

总结一下:

AsyncTask的cancel()方法并不是真的去立刻取消任务,只是将任务标记为取消状态,如果想立刻取消Async,必须手动根据这个状态去停止相应的进程。

AsyncTask使用实例,异步加载图片的更多相关文章

  1. Android批量图片加载经典系列——使用LruCache、AsyncTask缓存并异步加载图片

    一.问题描述 使用LruCache.AsyncTask实现批量图片的加载并达到下列技术要求 1.从缓存中读取图片,若不在缓存中,则开启异步线程(AsyncTask)加载图片,并放入缓存中 2.及时移除 ...

  2. AsyncTask用法和异步加载图片

    AsyncTask:是Android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI ...

  3. 实例演示Android异步加载图片

    本文给大家演示异步加载图片的分析过程.让大家了解异步加载图片的好处,以及如何更新UI.首先给出main.xml布局文件:简单来说就是 LinearLayout 布局,其下放了2个TextView和5个 ...

  4. 实例演示Android异步加载图片(转)

    本文给大家演示异步加载图片的分析过程.让大家了解异步加载图片的好处,以及如何更新UI.首先给出main.xml布局文件:简单来说就是 LinearLayout 布局,其下放了2个TextView和5个 ...

  5. android listview 异步加载图片并防止错位

    网上找了一张图, listview 异步加载图片之所以错位的根本原因是重用了 convertView 且有异步操作. 如果不重用 convertView 不会出现错位现象, 重用 convertVie ...

  6. ListView异步加载图片,完美实现图文混排

    昨天参加一个面试,面试官让当场写一个类似于新闻列表的页面,文本数据和图片都从网络上获取,想起我还没写过ListView异步加载图片并实现图文混排效果的文章,so,今天就来写一下,介绍一下经验. Lis ...

  7. Android中ListView异步加载图片错位、重复、闪烁问题分析及解决方案

    我们在使用ListView异步加载图片的时候,在快速滑动或者网络不好的情况下,会出现图片错位.重复.闪烁等问题,其实这些问题总结起来就是一个问题,我们需要对这些问题进行ListView的优化. 比如L ...

  8. Android学习笔记(二)之异步加载图片

    最近在android开发中碰到比较棘手的问题,就是加载图片内存溢出.我开发的是一个新闻应用,应用中用到大量的图片,一个界面中可能会有上百张图片.开发android应用的朋友可能或多或少碰到加载图片内存 ...

  9. listview异步加载图片并防止错位

    android listview 异步加载图片并防止错位 网上找了一张图, listview 异步加载图片之所以错位的根本原因是重用了 convertView 且有异步操作. 如果不重用 conver ...

  10. Listview 异步加载图片之优化篇(有图有码有解释)

    在APP应用中,listview的异步加载图片方式能够带来很好的用户体验,同时也是考量程序性能的一个重要指标.关于listview的异步加载,网上其实很多示例了,中心思想都差不多,不过很多版本或是有b ...

随机推荐

  1. Vim常用插件——前端开发工具系列

    作为一名开发者,应该对编辑器之神Vim与神之编辑器Emacs有所耳闻吧.编辑器之战的具体细节有兴趣的童鞋可以google之. Vim最大的特点是打开速度快,功能强大,一旦掌握了其中的命令,编程过程双手 ...

  2. Environment.Exit(0) 、Application.Exit() 、this.Close() 、this.Dispose()的区别

    Application.Exit:通知winform消息循环退出.程序会等待所有的前台线程终止后才能真正退出.是一种强行退出方式,就像 Win32 的 PostQuitMessage().它意味着放弃 ...

  3. 文档类型DTD,DOCTYPE和浏览器模式

    出处:http://blog.csdn.net/freshlover/article/details/11616563 浏览器从服务端获取网页后会根据文档的DOCTYPE定义显示网页,如果文档正确定义 ...

  4. 【转】.NET 4.5 使用async和await关键字调用异步方法

    async和await关键字是.NET 4.5新增加的异步编程方式,通过使用这两个关键字可以轻松便捷的编写异步方法.使用async关键字声明异步方法,使用await关键字等待和获取异步方法返回的结果. ...

  5. springMVC介绍及配置

    Spring MVC的Controller用于处理用户的请求.Controller相当于Struts 1里的Action,他们的实现机制.运行原理都类似. Controller是个接口,一般直接继承A ...

  6. svn怎么下载代码到本地

    1. 在我们安装好svn时,在指定的目录中点击鼠标右键SVN Checkout,弹出以下窗口.(在文件夹下各自建好前后台的文件夹分别check) 2. 在URL of repository:(存储库的 ...

  7. cf449D. Jzzhu and Numbers(容斥原理 高维前缀和)

    题意 题目链接 给出\(n\)个数,问任意选几个数,它们\(\&\)起来等于\(0\)的方案数 Sol 正解居然是容斥原理Orz,然而本蒟蒻完全想不到.. 考虑每一种方案 答案=任意一种方案 ...

  8. UNIX/Linux系统管理技术手册(2)----bash脚本编程

    1. 一个简单的例子: $ vim readname.sh #file:readname.sh#!/bin/bash echo -n "Enter your name: " rea ...

  9. RocketMQ读书笔记1——简述

    [消息队列的功能介绍] 分布式消息队列可以提供应用解耦.流量削峰.消息分发.保证最终一致性.方便动态扩容等功能. [MQ使用场景1——应用解耦] 复杂的系统如电商系统,会存在多个子系统,如订单系统.库 ...

  10. recvfrom WSAEFAULT 10014 的错误记录

    在使用 recvfrom 时一直没报错, 像这样 recvfrom(sock, Data, , (sockaddr*)&server_addr, &send_size) 当我看见百度百 ...