安卓开发笔记——关于AsyncTask的使用
在安卓开发中,我们经常要进行一些耗时操作,比如数据库操作,获取网络资源,读取内存文件等等,当我们在处理这些耗时操作的时候,如果我们直接在UI主线程进行,那么可能会导致阻塞UI主线程,使得UI界面卡顿,带来很不好的用户体验,因此安卓也给我们提供了2个异步操作的类,Handler和AsyncTask。
今天先讲AsyncTask,AsyncTask类是Andorid提供给我们的一个轻量级异步类,算是一个框架,它对线程之间的通讯进行了封装,并且提供了简易的编程操作,使得我们可以很轻松的实现后台线程和UI主线程之间的通讯。
我写了一个异步获取网络图片的小例子,先来看实现效果:


以上是官网对AsyncTask的一些描述,大致意思是:
AsyncTask是一个易操作线程使用类,它可以帮助我们把后台线程处理程序的结果发送给UI主线程,使UI线程得到更新。
AsyncTask类提供了3个泛型参数(Params,Progress,Result)和4个执行步骤(下文会具体提及)
先来看下3个泛型参数

1、Params:这是一个任务参数,一般我们会定义成String类型的,例如本例子中要获取网络资源的URL地址
2、Progress:任务执行的刻度,一般我们会定义成Integer类型
3、Result:返回结果类型,例如本例中是对网络图片进行获取,那么它的返回类型应该是BitMap
再来看下4个步骤:

当我们的类去实现AsyncTask类的时候至少需要实现doInBackground(Params...)方法,这里作为学习,我把每一个的具体工作任务也说说
它的执行顺序是这样的 onPreExecute-->doInBackground-->onProgressUpdate-->onPostExecute
1、onPreExecute:这是一个预处理方法,在任务开始的时候执行,我们可以在这里进行一些控件的实例化,设置属性等。(非必须)
2、doInBackground:这是一个任务操作方法,也是最重要的一个方法,所有的耗时操作都应该在这里执行。(必须)
3、onProgressUpdate:这是一个进度即时更新方法,在这里我们可以即时更新任务滚动条的进度。(非必须,当在doInBackground里调用publishProgress时触发)
4、onPostExecute:这是一个任务结果处理方法,在doInBackground里执行完任务,会将结果通知给这个类,在这类中我们可以对UI进行更新操作(非必须)
上面的1、3、4是UI主线程触发调用的,所以可以对UI进行更新操作,而第2步是个异步操作,不能在里面进行UI的更新操作。

关于AsyncTask的调用,其实非常简单,我们在AsyncTask类被继承实现的时候,在主线程直接对其对象调用execute(Params..)方法即可。
好了,文字介绍到此结束,上代码:
1、布局文件
<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:gravity="center"
android:orientation="vertical"> <ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" /> <Button
android:id="@+id/bt_download"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下载图片" /> </LinearLayout>
2、AsyncTask的实现类
package com.example.asynctasktest; import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream; import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient; import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.widget.ImageView; public class MyAsyncTask extends AsyncTask<String, Integer, Bitmap> { private ImageView imageView;
private ProgressDialog progressDialog; public MyAsyncTask(ImageView imageView, ProgressDialog progressDialog) {
this.imageView = imageView;
this.progressDialog = progressDialog;
} /**
* 执行第一步 这里为预处理操作,被UI线程所调用(可以在这里完成进度条的属性设置)
*/
@Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog.setTitle("当前任务");
progressDialog.setMessage("正在下载图片,请稍后...");
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);//设置进度条样式,横项
progressDialog.show();
} /**
* 执行第二步 这里为异步线程,在这里处理耗时任务操作(比如:下载,读取文件)
* 通过调用publishProgress方法(传递即时任务进度)可以触发onProgressUpdate的执行
*/
@Override
protected Bitmap doInBackground(String... params) {
String path=params[0];
Bitmap bitmap=null;
HttpClient httpClient=new DefaultHttpClient();
HttpGet httpGet=new HttpGet(path);
InputStream inputStream=null;
try {
HttpResponse httpResponse=httpClient.execute(httpGet);
if(httpResponse.getStatusLine().getStatusCode()==200){
//连接成功
// HttpEntity entity=httpResponse.getEntity();
// byte[] data=EntityUtils.toByteArray(entity);
// bitmap=BitmapFactory.decodeByteArray(data, 0, data.length); inputStream=httpResponse.getEntity().getContent();
ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
long fileSize=httpResponse.getEntity().getContentLength();//文件总大小
byte[] data=new byte[1024];//每次读取的大小
int len=0;//本次读取的大小
int total=0;//累计读取的大小
while((len=inputStream.read(data))!=-1){
total+=len;//累计读取的大小
int values=(int) ((total/(float)fileSize)*100);//得到当前任务进行百分比
publishProgress(values);//触发onProgressUpdate更新即时进度
outputStream.write(data, 0, len);
}
byte[] result=outputStream.toByteArray();//转换为字节数组
bitmap=BitmapFactory.decodeByteArray(result, 0, result.length);
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(inputStream!=null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} return bitmap; } /**
* 执行第三步 这里为实时UI更新操作,被UI线程所调用 在这里可以即时更新(如进度条进度)
*/
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
progressDialog.setProgress(values[0]);
} /**
* 执行第四步 在这里会返回doInBackground的操作结果,被UI线程调用,更新最后UI结果
*/
@Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
progressDialog.dismiss();
imageView.setImageBitmap(result);
} }
3、主类
package com.example.asynctasktest; import android.app.ProgressDialog;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView; public class MainActivity extends ActionBarActivity { private ImageView imageView;
private Button bt_download;
private ProgressDialog progressDialog;//进度对话框
private String path="http://img.pconline.com.cn/images/photoblog/5/3/7/5/5375781/20096/6/1244302842840.jpg";//下载图片路径 @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); imageView=(ImageView) findViewById(R.id.imageView);
bt_download=(Button) findViewById(R.id.bt_download);
progressDialog=new ProgressDialog(this); bt_download.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
MyAsyncTask myAsyncTask=new MyAsyncTask(imageView,progressDialog);
myAsyncTask.execute(path);
}
}); } }
代码到此结束,注释很详细应该很好理解。
使用AsyncTask类,以下是几条必须遵守的准则:
- Task的实例必须在UI主线程中创建。
- execute方法必须在UI主线程中调用。
- 不要手动的调用onPreExecute(),onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法。
- 该task只能被执行一次,否则多次调用时将会出现异常。
当然AsyncTask类不止这些东西,还有线程池的概念,今天先不讲,过几天连同Handler一起说。
对于简单的异步操作,掌握这些已经够了。
项目代码:http://pan.baidu.com/s/1kTkTgm7
作者:Balla_兔子
出处:http://www.cnblogs.com/lichenwei/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
正在看本人博客的这位童鞋,我看你气度不凡,谈吐间隐隐有王者之气,日后必有一番作为!旁边有“推荐”二字,你就顺手把它点了吧,相得准,我分文不收;相不准,你也好回来找我!
安卓开发笔记——关于AsyncTask的使用的更多相关文章
- 安卓开发笔记——关于Handler的一些总结(上)
接上篇文章<安卓开发笔记——关于AsyncTask的使用>,今天来讲下在安卓开发里"重中之重"的另一个异步操作类Handler. 今天打算先讲下关于Handler的一些 ...
- 安卓开发30:AsyncTask的用法
http://blog.csdn.net/initphp/article/details/10392093 安卓开发笔记系列(43) 在开发Android应用时必须遵守单线程模型的原则: Andro ...
- 安卓开发笔记——深入Activity
在上一篇文章<安卓开发笔记——重识Activity >中,我们了解了Activity生命周期的执行顺序和一些基本的数据保存操作,但如果只知道这些是对于我们的开发需求来说是远远不够的,今天我 ...
- 安卓开发笔记——自定义广告轮播Banner(实现无限循环)
关于广告轮播,大家肯定不会陌生,它在现手机市场各大APP出现的频率极高,它的优点在于"不占屏",可以仅用小小的固定空位来展示几个甚至几十个广告条,而且动态效果很好,具有很好的用户& ...
- 安卓开发笔记——丰富多彩的TextView
随手笔记,记录一些东西~ 记得之前写过一篇文章<安卓开发笔记——个性化TextView(新浪微博)>:http://www.cnblogs.com/lichenwei/p/4411607. ...
- 安卓开发笔记——关于开源项目SlidingMenu的使用介绍(仿QQ5.0侧滑菜单)
记得去年年末的时候写过这个侧滑效果,当时是利用自定义HorizontalScrollView来实现的,效果如下: 有兴趣的朋友可以看看这篇文件<安卓开发笔记——自定义HorizontalScro ...
- 安卓开发笔记——打造万能适配器(Adapter)
为什么要打造万能适配器? 在安卓开发中,用到ListView和GridView的地方实在是太多了,系统默认给我们提供的适配器(ArrayAdapter,SimpleAdapter)经常不能满足我们的需 ...
- 安卓开发笔记——关于照片墙的实现(完美缓存策略LruCache+DiskLruCache)
这几天一直研究在安卓开发中图片应该如何处理,在网上翻了好多资料,这里做点小总结,如果朋友们有更好的解决方案,可以留言一起交流下. 内存缓存技术 在我们开发程序中要在界面上加载一张图片是件非常容易的事情 ...
- 安卓开发笔记——Fragment+ViewPager组件(高仿微信界面)
什么是ViewPager? 关于ViewPager的介绍和使用,在之前我写过一篇相关的文章<安卓开发复习笔记——ViewPager组件(仿微信引导界面)>,不清楚的朋友可以看看,这里就不再 ...
随机推荐
- go语言可变参数的坑
0x00 前提 对可变参数不了解的同学,可以先看这篇文章可变参数终极指南 0x01 第一个坑 不能通过空接口类型向可变参数传递一个普通的切片 ,需要将普通切片转换为空接口切片 0x02 第二个坑 可变 ...
- python获取软件安装列表2222
softer_installed_list ===================== 使用python编写的,获取本机软件安装列表,输出为html表格. * win7 32位环境下运行 * 使用的是 ...
- 【Unity笔记】制作小地图Minimap
真正的手把手教程,太棒了: http://forum.china.unity3d.com/thread-17192-1-1.html 或者是使用插件NJG MiniMap: http://www.ta ...
- jquery 异步处理
<!DOCTYPE html> <head> <script type="text/javascript" src="jquery-1.12 ...
- 【oneday_onepage】—— 日常用语
what do you do for living? 一般用在问对方的工作.如果直接说“what is your job?”会显得有点生硬了. i was wondering if you can t ...
- OC与AS3的观察者模式比较以及外部回调
一.要点 1.AS3的观察者模式,主要是体现在在哪个组件上监听,那么就在这个组件上分发事件,并且可以直接传递Function. 2.OC的观察者模式,主要是需要你指定观察的对象,和观察的对象方法sel ...
- JS函数重载解决方案
JS的函数定义可以指定形式参数名称,多多少少我们会以为js至少可以支持参数个数不同的方法重载,然而遗憾的是这仅仅是一个假象,js所有的参数都是以arguments传递过去的,这个参数类似于数组,在函数 ...
- jquery学习心得:一个很好的css和js函数调用的例子
统一目录下的资源结构图: <html><head> <link rel="stylesheet" href="gallery.css&quo ...
- C++中内存泄漏的几种情况
1. 在类的构造函数和析构函数中没有匹配的调用new和delete函数 两种情况下会出现这种内存泄露:一是在堆里创建了对象占用了内存,但是没有显示地释放对象占用的内存:二是在类的构造函数中动态的分配了 ...
- Kafka消息的可靠性测试--针对直播业务的方案选择
转自:http://blog.csdn.net/bailove/article/details/44240303 业务场景 来疯直播互动平台,每天有数百万人上下线,有数十万人同时参与互动直播聊天.用户 ...