java webasynctask_安卓开发笔记——关于AsyncTask的使用

在安卓开发中,我们经常要进行一些耗时操作,比如数据库操作,获取网络资源,读取内存文件等等,当我们在处理这些耗时操作的时候,如果我们直接在UI主线程进行,那么可能会导致阻塞UI主线程,使得UI界面卡顿,带来很不好的用户体验,因此安卓也给我们提供了2个异步操作的类,Handler和AsyncTask。

今天先讲AsyncTask,AsyncTask类是Andorid提供给我们的一个轻量级异步类,算是一个框架,它对线程之间的通讯进行了封装,并且提供了简易的编程操作,使得我们可以很轻松的实现后台线程和UI主线程之间的通讯。

我写了一个异步获取网络图片的小例子,先来看实现效果:

7c248897fe4c7b6c0abad4e70dc518ce.gif

da6fb0750b9cd67c024a8265898b937c.png

以上是官网对AsyncTask的一些描述,大致意思是:

AsyncTask是一个易操作线程使用类,它可以帮助我们把后台线程处理程序的结果发送给UI主线程,使UI线程得到更新。

AsyncTask类提供了3个泛型参数(Params,Progress,Result)和4个执行步骤(下文会具体提及)

先来看下3个泛型参数

da8eebb9fd97c270a9df0c12fb838458.png

1、Params:这是一个任务参数,一般我们会定义成String类型的,例如本例子中要获取网络资源的URL地址

2、Progress:任务执行的刻度,一般我们会定义成Integer类型

3、Result:返回结果类型,例如本例中是对网络图片进行获取,那么它的返回类型应该是BitMap

再来看下4个步骤:

49ed2f57f1f5f8d064b5c6d971f9a4b7.png

当我们的类去实现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的更新操作。

16ee40746289cddf5d60e974f12ce292.png

关于AsyncTask的调用,其实非常简单,我们在AsyncTask类被继承实现的时候,在主线程直接对其对象调用execute(Params..)方法即可。

好了,文字介绍到此结束,上代码:

1、布局文件

1

2 xmlns:tools="http://schemas.android.com/tools"

3 android:layout_width="match_parent"

4 android:layout_height="match_parent"

5 android:gravity="center"

6 android:orientation="vertical">

7

8

10 android:layout_width="wrap_content"

11 android:layout_height="wrap_content" />

12

13

15 android:layout_width="wrap_content"

16 android:layout_height="wrap_content"

17 android:text="下载图片" />

18

19

2、AsyncTask的实现类

1 packagecom.example.asynctasktest;2

3 importjava.io.ByteArrayOutputStream;4 importjava.io.IOException;5 importjava.io.InputStream;6 importjava.io.OutputStream;7

8 importorg.apache.http.HttpResponse;9 importorg.apache.http.client.ClientProtocolException;10 importorg.apache.http.client.HttpClient;11 importorg.apache.http.client.methods.HttpGet;12 importorg.apache.http.impl.client.DefaultHttpClient;13

14 importandroid.app.ProgressDialog;15 importandroid.graphics.Bitmap;16 importandroid.graphics.BitmapFactory;17 importandroid.os.AsyncTask;18 importandroid.widget.ImageView;19

20 public class MyAsyncTask extends AsyncTask{21

22 privateImageView imageView;23 privateProgressDialog progressDialog;24

25 publicMyAsyncTask(ImageView imageView, ProgressDialog progressDialog) {26 this.imageView =imageView;27 this.progressDialog =progressDialog;28 }29

30 /**

31 * 执行第一步 这里为预处理操作,被UI线程所调用(可以在这里完成进度条的属性设置)32 */

33 @Override34 protected voidonPreExecute() {35 super.onPreExecute();36 progressDialog.setTitle("当前任务");37 progressDialog.setMessage("正在下载图片,请稍后...");38 progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);//设置进度条样式,横项

39 progressDialog.show();40 }41

42 /**

43 * 执行第二步 这里为异步线程,在这里处理耗时任务操作(比如:下载,读取文件)44 * 通过调用publishProgress方法(传递即时任务进度)可以触发onProgressUpdate的执行45 */

46 @Override47 protectedBitmap doInBackground(String... params) {48 String path=params[0];49 Bitmap bitmap=null;50 HttpClient httpClient=newDefaultHttpClient();51 HttpGet httpGet=newHttpGet(path);52 InputStream inputStream=null;53 try{54 HttpResponse httpResponse=httpClient.execute(httpGet);55 if(httpResponse.getStatusLine().getStatusCode()==200){56 //连接成功57 //HttpEntity entity=httpResponse.getEntity();58 //byte[] data=EntityUtils.toByteArray(entity);59 //bitmap=BitmapFactory.decodeByteArray(data, 0, data.length);

60

61 inputStream=httpResponse.getEntity().getContent();62 ByteArrayOutputStream outputStream=newByteArrayOutputStream();63 long fileSize=httpResponse.getEntity().getContentLength();//文件总大小

64 byte[] data=new byte[1024];//每次读取的大小

65 int len=0;//本次读取的大小

66 int total=0;//累计读取的大小

67 while((len=inputStream.read(data))!=-1){68 total+=len;//累计读取的大小

69 int values=(int) ((total/(float)fileSize)*100);//得到当前任务进行百分比

70 publishProgress(values);//触发onProgressUpdate更新即时进度

71 outputStream.write(data, 0, len);72 }73 byte[] result=outputStream.toByteArray();//转换为字节数组

74 bitmap=BitmapFactory.decodeByteArray(result, 0, result.length);75 }76 } catch(ClientProtocolException e) {77 e.printStackTrace();78 } catch(IOException e) {79 e.printStackTrace();80 }finally{81 if(inputStream!=null){82 try{83 inputStream.close();84 } catch(IOException e) {85 e.printStackTrace();86 }87 }88 }89

90 returnbitmap;91

92 }93

94 /**

95 * 执行第三步 这里为实时UI更新操作,被UI线程所调用 在这里可以即时更新(如进度条进度)96 */

97 @Override98 protected voidonProgressUpdate(Integer... values) {99 super.onProgressUpdate(values);100 progressDialog.setProgress(values[0]);101 }102

103 /**

104 * 执行第四步 在这里会返回doInBackground的操作结果,被UI线程调用,更新最后UI结果105 */

106 @Override107 protected voidonPostExecute(Bitmap result) {108 super.onPostExecute(result);109 progressDialog.dismiss();110 imageView.setImageBitmap(result);111 }112

113 }

3、主类

1 packagecom.example.asynctasktest;2

3 importandroid.app.ProgressDialog;4 importandroid.os.Bundle;5 importandroid.support.v7.app.ActionBarActivity;6 importandroid.view.View;7 importandroid.view.View.OnClickListener;8 importandroid.widget.Button;9 importandroid.widget.ImageView;10

11 public class MainActivity extendsActionBarActivity {12

13 privateImageView imageView;14 privateButton bt_download;15 private ProgressDialog progressDialog;//进度对话框

16 private String path="http://img.pconline.com.cn/images/photoblog/5/3/7/5/5375781/20096/6/1244302842840.jpg";//下载图片路径

17

18 @Override19 protected voidonCreate(Bundle savedInstanceState) {20 super.onCreate(savedInstanceState);21 setContentView(R.layout.activity_main);22

23 imageView=(ImageView) findViewById(R.id.imageView);24 bt_download=(Button) findViewById(R.id.bt_download);25 progressDialog=new ProgressDialog(this);26

27 bt_download.setOnClickListener(newOnClickListener() {28

29 @Override30 public voidonClick(View v) {31 MyAsyncTask myAsyncTask=newMyAsyncTask(imageView,progressDialog);32 myAsyncTask.execute(path);33 }34 });35

36 }37

38

39 }

代码到此结束,注释很详细应该很好理解。

使用AsyncTask类,以下是几条必须遵守的准则:

Task的实例必须在UI主线程中创建。

execute方法必须在UI主线程中调用。

不要手动的调用onPreExecute(),onPostExecute(Result),doInBackground(Params...),onProgressUpdate(Progress...)这几个方法。

该task只能被执行一次,否则多次调用时将会出现异常。

当然AsyncTask类不止这些东西,还有线程池的概念,今天先不讲,过几天连同Handler一起说。

对于简单的异步操作,掌握这些已经够了。

作者:Balla_兔子

出处:http://www.cnblogs.com/lichenwei/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

正在看本人博客的这位童鞋,我看你气度不凡,谈吐间隐隐有王者之气,日后必有一番作为!旁边有“推荐”二字,你就顺手把它点了吧,相得准,我分文不收;相不准,你也好回来找我!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值