官方文档:
AsyncTask enables proper and easy use
of the UI thread. This class allows to perform background operations
and publish results on the UI thread without having to manipulate
threads and/or handlers.
AsyncTask能够更恰当和更简单的去使用UI线程。这个类允许执行后台操作和展现结果在UI线程上,无需操纵线程和/或处理程序。AsyncTask的内部实现是一个线程池,每个后台任务会提交到线程池中的线程执行,然后使用Thread+Handler的方式调用回调函数。
1.AsyncTask抽象出后台线程运行的五个状态:
分别是:1、准备运行,2、正在后台运行,3、进度更新,4、完成后台任务,5、取消任务,对于这五个阶段,AsyncTask提供了五个回调函数:
1、准备运行:onPreExecute(),该回调函数在任务被执行之后立即由UI线程调用。这个步骤通常用来建立任务,在用户接口(UI)上显示进度条。
2、正在后台运行:doInParams...),该回调函数由后台线程在onPreExecute()方法执行结束后立即调用。通常在这里执行耗时的后
台计算。计算的结果必须由该函数返回,并被传递到onPostExecute()中。在该函数内也可以使用
publishProgress(Progress...)来发布一个或多个进度单位(unitsof
progress)。这些值将会在onProgressUpdate(Progress...)中被发布到UI线程。
3. 进度更新:onProgressUpdate(Progress...),该函数由UI线程在publishProgress(Progress...)方法调用完后被调用。一般用于动态地显示一个进度条。
4. 完成后台任务:onPostExecute(Result),当后台计算结束后调用。后台计算的结果会被作为参数传递给这一函数。
5、取消任务:onCancelled (),在调用AsyncTask的cancel()方法时调用
2.使用:
AsyncTask必须使用子类。子类会覆盖至少一个方法(doInParams…)),通常将覆盖第二个(onPostExecute(结果)。
AsyncTask的构造函数有三个模板参数:<Params, Progress, Result>
1.Params,传递给后台任务的参数类型。
2.Progress,后台计算执行过程中,进步单位(progress units)的类型。(就是后台程序已经执行了百分之几了。)
3.Result, 后台执行返回的结果的类型。
AsyncTask并不总是需要使用上面的全部3种类型。标识不使用的类型很简单,只需要使用Void类型即可。
1 import java.io.InputStream; 2 3 import java.net.HttpURLConnection; 4 5 import java.net.URL; 6 7 import android.app.Activity; 8 9 import android.graphics.Bitmap; 10 11 import android.graphics.BitmapFactory; 12 13 import android.os.AsyncTask; 14 15 import android.os.Bundle; 16 17 import android.view.View; 18 19 import android.view.View.OnClickListener; 20 21 import android.widget.Button; 22 23 import android.widget.ImageView; 24 25 import android.widget.ProgressBar; 26 27 import android.widget.Toast; 28 29 /** 30 31 * AsyncTask 实现异步加载图片 32 33 */ 34 public class MainActivity extends Activity { 35 36 37 38 public static final String IMG_URL="http://images.51cto.com/images/index/Images/Logo.gif"; 39 40 Button btn_asynctask; 41 42 ImageView imgView; 43 44 ProgressBar progressBar; 45 46 protected void onCreate(Bundle savedInstanceState) { 47 48 super.onCreate(savedInstanceState); 49 50 setContentView(R.layout.activity_main); 51 52 //加载控件 53 54 imgView = (ImageView) this.findViewById(R.id.imageView); 55 56 btn_asynctask = (Button) this.findViewById(R.id.btn_AsyncTask); 57 58 progressBar = (ProgressBar) this.findViewById(R.id.progressBar); 59 60 //绑定监听器 61 62 btn_asynctask.setOnClickListener(new OnClickListener() { 63 64 @Override 65 66 public void onClick(View v) { 67 68 GetImgTask getImgTask = new GetImgTask(); 69 70 getImgTask.execute(IMG_URL); //执行该任务 71 72 } 73 74 }); 75 76 } 77 78 79 80 /**获取网络图片任务**/ 81 82 private class GetImgTask extends AsyncTask<String, Integer, Bitmap> { 83 84 85 86 /**在 doInParams...)之前被调用,在ui线程执行 **/ 87 88 @Override 89 90 protected void onPreExecute() { 91 92 imgView.setImageBitmap(null); 93 94 progressBar.setProgress(0); //进度条复位 95 96 } 97 98 99 100 /**在后台线程中执行的任务**/ 101 protected Bitmap doInString... params) { 102 103 104 105 publishProgress(0); //会调用onProgressUpdate更新界面 106 107 108 InputStream inputStream = null; 109 Bitmap imgBitmap = null; 110 try { 111 112 URL url = new URL(IMG_URL); 113 114 if(url != null) { 115 116 HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 117 118 connection.setConnectTimeout(2000); 119 120 connection.setDoInput(true); 121 122 connection.setRequestMethod("GET"); 123 124 int code = connection.getResponseCode(); 125 126 if(200 == code) { 127 128 inputStream = connection.getInputStream(); 129 130 imgBitmap = BitmapFactory.decodeStream(inputStream); 131 132 } 133 134 } 135 136 } catch (Exception e) { 137 138 e.printStackTrace(); 139 140 return null; 141 142 } 143 144 publishProgress(100); //下载完成,更新进度条为满格 145 146 //这里不是UI线程,故不能直接setImage(imgBitmap), 147 148 return imgBitmap; 149 150 } 151 152 153 154 /**在调用publishProgress之后被调用,在ui线程执行 **/ 155 156 @Override 157 158 protected void onProgressUpdate(Integer... values) { 159 160 progressBar.setProgress(values[0]); //设置进度条的进度 161 162 } 163 164 /**在后台线程执行完成之后,调用该方法,获取数据更新界面**/ 165 166 @Override 167 168 protected void onPostExecute(Bitmap result) { 169 170 if(result != null) { 171 172 Toast.makeText(MainActivity.this, "成功获取图片", Toast.LENGTH_LONG).show(); 173 174 imgView.setImageBitmap(result); 175 176 }else { 177 178 Toast.makeText(MainActivity.this, "获取图片失败", Toast.LENGTH_LONG).show(); 179 180 } 181 } 182 183 /**取消任务,在ui线程执行 **/ 184 protected void onCancelled() { 185 186 progressBar.setProgress(0);//进度条复位 187 188 super.onCancelled(); 189 } 190 } 191 }
分析:
1.点击按钮之后,创建一个任务,参数值为url(所以第一个参数为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()中返回的对象。