一、为什么要使用 AsyncTask
1、平时我们在开发Android程序时遇到较耗时任务的处理,如I/O访问的数据库操作、网络访问等情况时造成UI假死等问题,通过 AsyncTask可以很好的解决这个问题。
二、解决上面第一点的问题有以下方法:
1、方法一:创建一个新的线程执行我们的任务,使用Thread类,在 run(){}中写入任务代码,比如:
new Thread(new Runnable()
{
public void run()
{
Downloader.downloadFile(url);
}
}).start();
但使用Thread会产生一些意想不到的问题,需要程序员用更多的代码手动的维护它。
2、方法二:Android SDK为我们提供了一个后台任务的处理工具AsyncTask。AsyncTask就是一个封装过的后台任务类,顾名思义就是异步任务,方便我们维护,Android开发网提示这样的好处可以解决一些线程安全问题,AsyncTask直接继承于Object类,位置为 android.os.AsyncTask。要使用AsyncTask工作我们要提供三个泛型参数,并重载四个方法(至少重载一个)。
三个泛型:
(1)Params:任务执行器需要的数据类型
(2)Progress:后台计算中使用的进度单位数据类型
(3)Result:后台计算返回结果的数据类型
有些参数是可以设置为不使用的,只要传递为void类型即可,比如:AsyncTask
四个步骤:
(1)onPreExecute():执行预处理,它运行于UI线程,可以为后台任务做一些准备工作,比如绘制一个进度条控件。
(2)doInBackground(Params...):后台进程执行的具体计算在这里实现,doInBackground(Params...)是AsyncTask的关键,此方法必须重载。在这个方法内可以使用 publishProgress(Progress...)改变当前的进度值。
(3)onProgressUpdate(Progress...):运行于UI线程。如果在doInBackground(Params...) 中使用了publishProgress(Progress...),就会触发这个方法。在这里可以对进度条控件根据进度值做出具体的响应。
(4)onPostExecute(Result):运行于UI线程,可以对后台任务的结果做出处理,结果就是doInBackground(Params...)的返回值。此方法也要经常重载,如果Result为null表明后台任务没有完成(被取消或者出现异常)。
AsyncTask<Params, Progress, Result>
Params:任务执行器需要的数据类型,传递给doInBackground(Params)的类型即后台运行任务的参数类型
Progress:后台计算中使用的进度单位数据类型,传递给onProgressUpdate(Progress)的参数类型
Result:后台计算返回结果的数据类型,传递给onPostExecute(Result)的参数类型
1 public class AsyncTaskDemo2 extends Activity 2 { 3 private Button btnAsyncTaskDemo2_Start, btnAsyncTaskDemo2_Stop; 4 private TextView tvProgress; 5 private ProgressBar pb1; 6 private int count = 1; 7 private final int TOTAL = 100; 8 private final int SLEEP = 10; 9 //下载的异步任务 10 private DownLoad dl = null; 11 12 13 @Override 14 protected void onCreate(Bundle savedInstanceState) 15 { 16 super.onCreate(savedInstanceState); 17 setContentView(R.layout.asynctaskdemo2); 18 //初始化组件 19 initComponent(); 20 //注册监听 21 registerListener(); 22 } 23 24 /** 25 * 函数名称 : initComponent 26 * 功能描述 : 初始化组件 27 * 参数及返回值说明: 28 * 29 * 修改记录: 30 * 日期 :2012-2-14 下午4:21:19 修改人:gy 31 * 描述 : 32 * 33 */ 34 private void initComponent() 35 { 36 btnAsyncTaskDemo2_Start = (Button)findViewById(R.id.btnAsyncTaskDemo2_Start); 37 btnAsyncTaskDemo2_Stop = (Button)findViewById(R.id.btnAsyncTaskDemo2_Stop); 38 tvProgress = (TextView)findViewById(R.id.tvProgress); 39 pb1 = (ProgressBar)findViewById(R.id.pb1); 40 } 41 42 /** 43 * 函数名称 : registerListener 44 * 功能描述 : 注册监听 45 * 参数及返回值说明: 46 * 47 * 修改记录: 48 * 日期 :2012-2-14 下午4:21:23 修改人:gy 49 * 描述 : 50 * 51 */ 52 private void registerListener() 53 { 54 //开始 55 btnAsyncTaskDemo2_Start.setOnClickListener(new OnClickListener() 56 { 57 @Override 58 public void onClick(View v) 59 { 60 dl = new DownLoad(); 61 System.out.println("=====dl.execute方法调用之前====="); 62 //执行任务,此方法的参数:是任务执行器需要的数据类型,传递给doInBackground(Params)的类型即后台运行任务的参数类型 63 dl.execute(new Integer(TOTAL)); 64 System.out.println("=====dl.execute方法调用之后====="); 65 } 66 }); 67 68 //停止 69 btnAsyncTaskDemo2_Stop.setOnClickListener(new OnClickListener() 70 { 71 @Override 72 public void onClick(View v) 73 { 74 if(dl != null) 75 { 76 dl.cancel(true); 77 } 78 Toast.makeText(AsyncTaskDemo2.this, "停止下载", Toast.LENGTH_LONG).show(); 79 } 80 }); 81 } 82 83 /** 84 * ********************************************************** 85 * 内容摘要 :下载的异步任务类<p> 86 * 87 * 作者 :kyx 88 * 创建时间 :2012-2-14 下午4:27:36 89 * 当前版本号:v1.0 90 * 历史记录 : 91 * 日期 : 2012-2-14 下午4:27:36 修改人: 92 * 描述 : 93 *********************************************************** 94 */ 95 class DownLoad extends AsyncTask<Object, Object, Object> 96 { 97 98 /** 99 * 函数名称 :onPreExecute 100 * 功能描述 :当任务执行之前开始调用此方法,执行预处理,它运行于UI线程,可以为后台任务做一些准备工作 101 * 参数说明 : 102 * 返回值: 103 * 104 * 修改记录: 105 * 日期 :2012-2-14 下午4:28:16 修改人:gy 106 * 描述 : 107 * 108 */ 109 @Override 110 protected void onPreExecute() 111 { 112 //重置UI 113 resetUI(); 114 115 } 116 117 /** 118 * 函数名称 : resetUI 119 * 功能描述 : 重置UI 120 * 参数及返回值说明: 121 * 122 * 修改记录: 123 * 日期 :2012-2-15 下午2:29:01 修改人:gy 124 * 描述 : 125 * 126 */ 127 private void resetUI() 128 { 129 //将计数器重置为1 130 count = 1; 131 //将进度条重置为0 132 pb1.setProgress(0); 133 } 134 135 /** 136 * 函数名称 :doInBackground 137 * 功能描述 :此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间 138 * 参数说明 : 139 * @param params 任务执行器需要的数据类型,传递给doInBackground(Params)的类型即后台运行任务的参数类型 140 * @return 141 * 返回值:任务执行的结果返回 142 * 143 * 修改记录: 144 * 日期 :2012-2-14 下午4:26:20 修改人:gy 145 * 描述 : 146 * 147 */ 148 @Override 149 protected Object doInBackground(Object... params) 150 { 151 int iMax = ((Integer)params[0]).intValue(); 152 System.out.println("iMax:" + iMax); 153 for(;count <= iMax; count++) 154 { 155 System.out.println("=====doInBackground(Object... params)开始===== count=" + count); 156 System.out.println("this.isCancelled()=" + this.isCancelled()); 157 //如果调用了 cancel 方法,则 isCancelled 返回为 true,反之返回 false 158 if(this.isCancelled()) 159 { 160 break; 161 } 162 //通知更改 UI 线程 163 publishProgress(new Integer(count)); 164 try 165 { 166 Thread.sleep(SLEEP); 167 } 168 catch (InterruptedException e) 169 { 170 e.printStackTrace(); 171 } 172 } 173 174 StringBuffer sb = new StringBuffer(); 175 sb.append("下载结束"); 176 return sb.toString(); 177 } 178 179 /** 180 * 函数名称 :onProgressUpdate 181 * 功能描述 :此方法运行于UI线程,用于显示任务执行的进度。 182 * 如果在doInBackground(Params...) 中调用了publishProgress(Progress...),就会触发这个方法 183 * 参数说明 : 184 * @param values publishProgress 方法传来的参数 185 * 返回值: 186 * 187 * 修改记录: 188 * 日期 :2012-2-14 下午4:28:28 修改人:gy 189 * 描述 : 190 * 191 */ 192 @Override 193 protected void onProgressUpdate(Object... values) 194 { 195 196 if(values != null) 197 { 198 int currCount = ((Integer)values[0]).intValue(); 199 //更新进度条信息 200 pb1.setProgress(currCount); 201 tvProgress.setText(currCount + "%"); 202 } 203 204 } 205 206 /** 207 * 函数名称 :onPostExecute 208 * 功能描述 :此方法运行于UI线程,任务执行的结果作为此方法的参数返回。 209 * 可以对后台任务的结果做出处理,结果就是doInBackground(Params...)的返回值 210 * 参数说明 : 211 * @param result doInBackground(Params...)的返回值 212 * 返回值: 213 * 214 * 修改记录: 215 * 日期 :2012-2-14 下午4:28:34 修改人:gy 216 * 描述 : 217 * 218 */ 219 @Override 220 protected void onPostExecute(Object result) 221 { 222 223 Toast.makeText(AsyncTaskDemo2.this, result.toString(), Toast.LENGTH_LONG).show(); 224 225 226 } 227 228 /** 229 * 函数名称 :onCancelled 230 * 功能描述 :取消任务,当调用异步任务的 cancel 方法时会触发 onCancelled 方法 231 * 参数说明 : 232 * 返回值: 233 * 234 * 修改记录: 235 * 日期 :2012-2-14 下午4:28:40 修改人:gy 236 * 描述 : 237 * 238 */ 239 @Override 240 protected void onCancelled() 241 { 242 super.onCancelled(); 243 } 244 } 245 }