Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面
Android异步处理二:使用AsyncTask异步更新UI界面
Android异步处理三:Handler+Looper+MessageQueue深入详解
Android异步处理四:AsyncTask的实现原理

Android异步处理二:使用AsyncTask异步更新UI界面

概述:AsyncTask是在Android SDK 1.5之后推出的一个方便编写后台线程与UI线程交互的辅助类。AsyncTask的内部实现是一个线程池,每个后台任务会提交到线程池中的线程执行,然后使用Thread+Handler的方式调用回调函数(如需深入了解原理请看《Android异步处理四:AsyncTask的实现原理》)。

AsyncTask抽象出后台线程运行的五个状态,分别是:1、准备运行,2、正在后台运行,3、进度更新,4、完成后台任务,5、取消任务,对于这五个阶段,AsyncTask提供了五个回调函数:

1、准备运行:onPreExecute(),该回调函数在任务被执行之后立即由UI线程调用。这个步骤通常用来建立任务,在用户接口(UI)上显示进度条。

2、正在后台运行:doInBackground(Params...),该回调函数由后台线程在onPreExecute()方法执行结束后立即调用。通常在这里执行耗时的后台计算。计算的结果必须由该函数返回,并被传递到onPostExecute()中。在该函数内也可以使用publishProgress(Progress...)来发布一个或多个进度单位(unitsof progress)。这些值将会在onProgressUpdate(Progress...)中被发布到UI线程。

3. 进度更新:onProgressUpdate(Progress...),该函数由UI线程在publishProgress(Progress...)方法调用完后被调用。一般用于动态地显示一个进度条。

4. 完成后台任务:onPostExecute(Result),当后台计算结束后调用。后台计算的结果会被作为参数传递给这一函数。

5、取消任务:onCancelled (),在调用AsyncTask的cancel()方法时调用

AsyncTask的构造函数有三个模板参数:

1.Params,传递给后台任务的参数类型。

2.Progress,后台计算执行过程中,进步单位(progress units)的类型。(就是后台程序已经执行了百分之几了。)

3.Result, 后台执行返回的结果的类型。

AsyncTask并不总是需要使用上面的全部3种类型。标识不使用的类型很简单,只需要使用Void类型即可。

例子:与《Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面》实现的例子相同,我们在后台下载CSDN的LOGO,下载完成后在UI界面上显示出来,并会模拟下载进度更新。

AsyncTaskActivity.java

 1 package com.zhuozhuo; 2  3  4 import org.apache.http.HttpResponse; 5 import org.apache.http.client.HttpClient; 6 import org.apache.http.client.methods.HttpGet; 7 import org.apache.http.impl.client.DefaultHttpClient; 8  9 import android.app.Activity;10 import android.graphics.Bitmap;11 import android.graphics.BitmapFactory;12 import android.os.AsyncTask;13 import android.os.Bundle;14 import android.view.View;15 import android.view.View.OnClickListener;16 import android.widget.Button;17 import android.widget.ImageView;18 import android.widget.ProgressBar;19 import android.widget.Toast;20 21 public class AsyncTaskActivity extends Activity {22     23     private ImageView mImageView;24     private Button mButton;25     private ProgressBar mProgressBar;26     27     @Override28     public void onCreate(Bundle savedInstanceState) {29         super.onCreate(savedInstanceState);30         setContentView(R.layout.main);31         32         mImageView= (ImageView) findViewById(R.id.imageView);33         mButton = (Button) findViewById(R.id.button);34         mProgressBar = (ProgressBar) findViewById(R.id.progressBar);35         mButton.setOnClickListener(new OnClickListener() {36             37             @Override38             public void onClick(View v) {39                 GetCSDNLogoTask task = new GetCSDNLogoTask();40                 task.execute("http://csdnimg.cn/www/images/csdnindex_logo.gif");41             }42         });43     }44     45     class GetCSDNLogoTask extends AsyncTask<String,Integer,Bitmap> {//继承AsyncTask46 47         @Override48         protected Bitmap doInBackground(String... params) {//处理后台执行的任务,在后台线程执行49             publishProgress(0);//将会调用onProgressUpdate(Integer... progress)方法50             HttpClient hc = new DefaultHttpClient();51             publishProgress(30);52             HttpGet hg = new HttpGet(params[0]);//获取csdn的logo53             final Bitmap bm;54             try {55                 HttpResponse hr = hc.execute(hg);56                 bm = BitmapFactory.decodeStream(hr.getEntity().getContent());57             } catch (Exception e) {58                 59                 return null;60             }61             publishProgress(100);62             //mImageView.setImageBitmap(result); 不能在后台线程操作ui63             return bm;64         }65         66         protected void onProgressUpdate(Integer... progress) {//在调用publishProgress之后被调用,在ui线程执行67             mProgressBar.setProgress(progress[0]);//更新进度条的进度68          }69 70          protected void onPostExecute(Bitmap result) {//后台任务执行完之后被调用,在ui线程执行71              if(result != null) {72                  Toast.makeText(AsyncTaskActivity.this, "成功获取图片", Toast.LENGTH_LONG).show();73                  mImageView.setImageBitmap(result);74              }else {75                  Toast.makeText(AsyncTaskActivity.this, "获取图片失败", Toast.LENGTH_LONG).show();76              }77          }78          79          protected void onPreExecute () {//在 doInBackground(Params...)之前被调用,在ui线程执行80              mImageView.setImageBitmap(null);81              mProgressBar.setProgress(0);//进度条复位82          }83          84          protected void onCancelled () {//在ui线程执行85              mProgressBar.setProgress(0);//进度条复位86          }87         88     }89     90 91 }

main.xml

1 <?xml version="1.0" encoding="utf-8"?>2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"3     android:orientation="vertical" android:layout_width="fill_parent"4     android:layout_height="fill_parent">5     <ProgressBar android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/progressBar" style="?android:attr/progressBarStyleHorizontal"></ProgressBar>6     <Button android:id="@+id/button" android:text="下载图片" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>7     <ImageView android:id="@+id/imageView" android:layout_height="wrap_content"8         android:layout_width="wrap_content" />9 </LinearLayout>

manifest.xml

 1 <?xml version="1.0" encoding="utf-8"?> 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 3       package="com.zhuozhuo" 4       android:versionCode="1" 5       android:versionName="1.0"> 6     <uses-sdk android:minSdkVersion="10" /> 7 <uses-permission android:name="android.permission.INTERNET"></uses-permission> 8     <application android:icon="@drawable/icon" android:label="@string/app_name"> 9         <activity android:name=".AsyncTaskActivity"10                   android:label="@string/app_name">11             <intent-filter>12                 <action android:name="android.intent.action.MAIN" />13                 <category android:name="android.intent.category.LAUNCHER" />14             </intent-filter>15         </activity>16 17     </application>18 </manifest>

运行结果:

Android异步处理系列文章四篇之二 使用AsyncTask异步更新UI界面

流程说明:

1、 当点击按钮时,创建一个task,并且传入CSDN的LOGO地址(String类型参数,因此AsyncTask的第一个模板参数为String类型)

2、 UI线程执行onPreExecute(),把ImageView的图片清空,progrssbar的进度清零。

3、 后台线程执行doInBackground(),不可以在doInBackground()操作ui,调用publishProgress(0)更新进度,此时会调用onProgressUpdate(Integer...progress)更新进度条(进度用整形表示,因此AsyncTask的第二个模板参数是Integer)。函数最后返回result(例子中是返回Bitmap类型,因此AsyncTask的第个模板参数是Bitmap)。

4、 当后台任务执行完成后,调用onPostExecute(Result),传入的参数是doInBackground()中返回的对象。

总结:

AsyncTask为我们抽象出一个后台任务的五种状态,对应了五个回调接口,我们只需要根据不同的需求实现这五个接口(doInBackground是必须要实现的),就能完成一些简单的后台任务。使用AsyncTask的方式使编写后台进程和UI进程交互的代码变得更为简洁,使用起来更加方便,但是,AsyncTask也有一些缺憾,我们留到以后再讲。

转自:http://blog.csdn.net/mylzc/article/details/6772129

更多相关文章

  1. C语言函数以及函数的使用
  2. Android——多线程
  3. Android中回调函数的理解---本人Android纯新手
  4. input系统一 loop线程的创建与运行
  5. 【Android NDK 开发】Ubuntu 函数库交叉编译 ( Android 动态库交
  6. AndroidUI线程机制
  7. 修改android公共控件和后台服务
  8. Android 后台Service : 向服务器发送心跳包
  9. Android学习札记12:对Parcelable中describeContents()函数的一种

随机推荐

  1. Android(安卓)PureMVC
  2. android触摸实现物体运动方式
  3. My Android成长之路(四)——【xml解析之X
  4. ubuntu NDK 的安装
  5. Sending email without user interaction
  6. Android(安卓)中文 API (35) —— ImageSwi
  7. Android(安卓)EditText不弹出软键盘
  8. android开发 列表显示(ListView)
  9. android 电容屏(二):驱动调试之基本概念篇
  10. Android(安卓)后台任务(五)Service