摘要
AsyncTask能够合理且轻松使用UI线程,该类允许执行后台操作和发送结果到UI线程而不需要操作threads或handlers。
AsyncTask是针对Thread和Handler代替而封装好的一个工具,但不构成一个通用的线程框架。AsyncTask最理想地被用于短暂的操作,如果你需要长时间保持线程运行,建议最好使用java.util.concurrent包提供的Executor、ThreadPoolExecutor、FutureTask等类。
一个异步任务被评估后定义并在后台线程运行,将结果发送回UI线程。一个异步任务由三个泛型和四个步骤组成,三个泛型分别是:Params、Progress和Result,四个方法分别是:onPreExecute、doInBackground、onProgressUpdate和onPostExecute。
简单Demo介绍
AsyncTask必须作为一个子类使用,该子类将至少重写一个方法(doInBackground(Params...)),通常还重写另一个方法(onPostExecute(Result))
下面是一个简单的例子:
- private class DonwloadFilesTask extends AsyncTask<URL, Integer, Long> {
- @Override
- protected void onPreExecute() {
- // TODO Auto-generated method stub
- super.onPreExecute();
- // 显示下载进度条
- mProgressDialog.show();
- }
- @Override
- protected Long doInBackground(URL... params) {
- int count = params.length;
- long totalsize = 0;
- for (int i = 0; i < count; i++) {
- totalsize += Downloader.loadFile(params[i]);
- publishProgress((int) ((i / (float) count) * 100));//更新进度条
- if (isCancelled())
- break;
- }
- return totalsize;//返回下载数据大小,在onPostExecute()方法中处理
- }
- @Override
- protected void onProgressUpdate(Integer... values) {
- // TODO Auto-generated method stub
- super.onProgressUpdate(values);
- setProgressPercent(values[0]);
- }
- @Override
- protected void onPostExecute(Long result) {
- // TODO Auto-generated method stub
- super.onPostExecute(result);
- showDialog("Downloaded " + result + " bytes");
- mProgressDialog.dismiss();
- }
- }
在UI线程中创建Task,然后执行。
- new DonwloadFilesTask().execute(mUrl1,mUrl2,mUrl3);
AsyncTask通用的类型
1、Params,被发送到task中执行的元素类型
2、Progress,后台计算传送进度类型
3、Result,后台计算结果类型
在一个异步任务中并不是所有的类型都是必须的,为了标记一个类型是无用的,通常使用Void:
private class MyTask extends AsyncTask
四个步骤
当一个异步任务被执行,该异步任务需要经历四个步骤:
1、onPreExecute(),异步任务执行之前在UI thread中调用,通常被用来创建当前任务,实例化进度条对象
2、doInBackground(Params...),在执行完onPreExecute()后立即被调用的方法,通常被用来执行后台可能需要花费很长时间的计算。异步任务传入的元素在这里被调用,计算的结果必须通过当前步骤返回并传送到最后的onPostExecute()方法中。在这个步骤中,可能需要使用publishProgress(Progress...)方法来公布一个或多个进度单元值,这些进度单元值被公布在UI线程中,在onProgressUpdate(Progress...)中调用
3、onProgressUpdate(Progress...),该方法在publishProgress(Progress...)被回调后调用,执行的时间长短未被定义,但该方法显示任务还在后台执行的进度信息,比如:你可以被用来展示进度条动画或打印出logs信息
4、onPostExecute(Result),在异步任务结束后在UI thread中调用的方法,后台计算的结果被作为一个参数传递到该步骤
取消异步任务
调用cancle(boolean)方法取消还在执行的异步任务,调用该方法后将会回调isCancelled()方法返回true。在调用该方法后,onCancelled(Object)代替了onPostExecute(Object)在执行完doInBackground(Object[])后回调。为了保证当前任务尽快被取消,你应该经常检查isCancelled()返回值情况
线程规则
为保证AsyncTask类能够正确执行,下面是几个需要遵循的线程规则:
1、AsyncTask类必须在UI线程中被加载
2、AsyncTask类实例必须在UI线程中实例化
3、execute(Params...)方法必须在UI线程中调用
4、不允许手动回调 onPreExecute(), onPostExecute(Result), doInBackground(Params...), onProgressUpdate(Progress...)方法
5、当前任务只能被执行一次(否则抛出异常)
Memory observability
通过下面操作步骤,AsyncTask保证所有回调都是异步、安全的:
1、在构造方法或onPreExecute()中设置成员变量,在doInBackground()方法中引用
2、在doInBackground()中设置成员变量,在onProgressUpdate(Progress...)和onPostExecute()方法中引用
AsyncTask执行的顺序
正如前面介绍的,AsyncTask是被序列化执行在单一的后台线程中,从DONUT版本开始,改变一个线程池允许多个任务并行操作。从HONEYCOMB版本开始,在一个单一的线程上执行任务,以避免并行执行导致常见的应用错误。
如果你确实想并发执行,你可以调用executeOnExecutor(java.util.concurrent.Executor, Object[]) 通过THREAD_POOL_EXECUTOR
推荐阅读:
你可能感兴趣的文章
转载请注明出处: https://www.teachcourse.cn/1535.html ,谢谢支持!