Android线程一、AsyncTask使用简介
来源:互联网 发布:画框图软件 编辑:程序博客网 时间:2024/06/04 18:49
写在前面
AsyncTask简介
AsyncTask异步任务,是Android提供给我们的一个处理异步任务的类. 通过该类,可以实现UI线程和后台线程间的通讯. 后台线程执行异步任务,并将结果及进度传递给UI线程,由UI线程做相应处理和显示.
为什么使用异步任务(子线程操作)
- Android中只有UI线程能进行更新UI的操作. 这样能保证UI的稳定性和准确性,避免多个线程同时对UI进行操作,造成UI混乱.
- 但Android是一个多线程的OS,一些耗时操作,如请求网络、图片加载、文件读取等放在UI线程会造成后面任务的阻塞,从而出现ANR(Application not responsed)异常. 所以需要将耗时操作放在子线程中执行,这样既避免了Android的单线程模型,又避免了ANR异常.
AsyncTask为何而生
- UI线程能更新UI,子线程不能更新UI.
- 当子线程操作过程中需要更新UI时需借助Handler,比较麻烦.
- AsyncTask方便我们在子线程中更新UI. 即对基于线程池的子线程和Handler的封装.
AsyncTask类的介绍
构建AsyncTask子类的参数
AsyncTask<Params, Progress, Result>
是一个抽象类,通常用于被继承. 继承AsyncTask需要指定如下三个泛型参数- Params:启动任务时输入的参数类型(如String).
- Progress:后台任务执行中返回进度值的类型(如Integer).
- Result:后台任务执行完成后返回结果的类型(如Bitmap).
构建AsyncTask子类的回调方法
doInBackground()
:必须重写,异步执行后台线程要完成的任务,耗时操作将在此方法中完成.onPreExecute()
:执行后台耗时操作前被调用,通常用于进行初始化操作.onPostExecute()
:当doInBackground方法完成后,系统将自动调用此方法,并将doInBackground方法返回的值传入此方法. 通过此方法进行UI的更新.onProgressUpdate()
:当在doInBackground方法中调用publishProgress方法更新任务执行进度后,将调用此方法. 通过此方法我们可以知晓任务的完成进度.
Android异步加载案例一、加载图片
AsyncTask的实现
/** * 1. 体验AsyncTask各个方法的执行顺序 * onPreExecute最先执行. 然后执行doInBackground * doInBackground调用publisProgress()后执行onProgressUpdate * doInBackground执行结束返回结果给onPostExecute执行 * * 2. 加载网络图片onPostExecute */// arg1、2、3参考上面AsyncTask类的介绍// arg1:输入的图片地址类型. arg2:异步任务执行完毕返回的结果类型class MyAsyncTask extends AsyncTask<String, Void, Bitmap> { @Override protected void onPreExecute() { super.onPreExecute(); pb.setVisibility(View.VISIBLE); LogTool.d(TAG, "onPreExecute..."); // 异步任务执行之前的初始化操作 } // 可变参数为启动任务时输入的参数类型 @Override protected Bitmap doInBackground(String... params) { // 获取传递进来的参数,即图片地址 String url = params[0]; Bitmap bitmap = null; URLConnection conn; InputStream is = null; // 使用InputStream读取流数据 BufferedInputStream bis = null; try { conn = new URL(url).openConnection(); is = conn.getInputStream(); bis = new BufferedInputStream(is); bitmap = BitmapFactory.decodeStream(bis); } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); bis.close(); } catch (IOException e) { e.printStackTrace(); } } LogTool.d(TAG, "doInBackground..."); publishProgress(); // 异步任务执行过程中调用onProgressUpdate更新界面进度 return bitmap; } // 参数为doInBackground执行完毕返回的结果对象 @Override protected void onPostExecute(Bitmap bitmap) { super.onPostExecute(bitmap); pb.setVisibility(View.GONE); iv.setImageBitmap(bitmap); LogTool.d(TAG, "onPostExecute..."); } // 被doInBackground使用publishProgress后进行进度的更新 @Override protected void onProgressUpdate(Void... values) { super.onProgressUpdate(values); LogTool.d(TAG, "onProgressUpdate..."); }}
AsyncTask的调用
/*** 在UI线程(如onCreate()方法)中创建异步任务实例*/private static final String TAG = "AsyncTaskActivity";private static final String IMAGE_URL = "..."; // 图片地址private ImageView iv;private ProgressBar pb;// 这里有个BUG,由AsyncTask底层线程机制导致. 在案例二中提供解决方案.private MyAsyncTask myTask;@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_async_task); iv = (ImageView) findViewById(R.id.iv_bg); pb = (ProgressBar) findViewById(R.id.pb_bg); // *** execute中的参数将传递给doInBackground() *** myTask = new MyAsyncTask(); myTask.execute(IMAGE_URL);}
Android异步加载案例二、更新进度
AsyncTask的实现
class ProgressBarAsyncTask extends AsyncTask<Void, Integer, Void> { @Override protected Void doInBackground(Void... voids) { // 通过for循环模拟进度条的进度 for (int i = 0; i < 30; i++) { if (isCancelled()) { break; } // 通过publishProgress方法将调用onProgressUpdate来更新进度 publishProgress(i); // 通过休眠模拟耗时操作 SystemClock.sleep(300); } /** * 当for循环全部执行完毕才会进行下一个Task任务,由AsyncTask底层的基于线程池引起的 * * 解决方案,将AsyncTask生命周期与当前所在Activity绑定 */ return null; } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); if (isCancelled()) { // 若线程结束,进度条置空 return; } // 通过publishProgress方法传过来的值进行进度更新 pb_schedule.setProgress(values[0]); }}
绑定AsyncTask的生命周到Activity中
@Override protected void onPause() { super.onPause(); if (pbTask != null && pbTask.getStatus().equals(AsyncTask.Status.RUNNING)) { // 注意:cancel方法仅将AsyncTask任务置为CANCEL状态,并未真正结束线程 pbTask.cancel(true); }}
AsyncTask的调用
private ProgressBarAsyncTask pbTask;@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_async_task); pb_schedule = (ProgressBar) findViewById(R.id.pb_schedule); pbTask = new ProgressBarAsyncTask(); pbTask.execute(); // 输入参数为空}
使用AsyncTask的注意事项
- 必须在UI线程中创建AsyncTask的实例.
- 只能在UI线程中调用AsyncTask的
execute()
方法. - AsyncTask被重写的四个方法是系统自动调用的,不应手动调用.
- 每个AsyncTask只能被执行一次,多次执行将会引发异常.
- AsyncTask的四个方法,只有
doInBackground()
方法是运行在其他线程中,其他三个方法都运行在UI线程中,可以对UI进行更新操作.
以上。如有错误和疑问,欢迎指正提出。 catface.wyh@gmail.com
- Android线程一、AsyncTask使用简介
- 线程使用教程 一 Asynctask
- Android之线程使用AsyncTask异步任务(一)
- 使用Android AsyncTask异步线程
- android之多线程工作(一)AsyncTask
- android 异步线程AsyncTask类的使用
- Android的异步线程AsyncTask的使用
- android:线程池和AsyncTask使用小结
- Android线程和线程池(一)--AsyncTask
- Android中线程形态AsyncTask、HandlerThread 和 IntentService简介
- Android--AsyncTask简介
- Android AsyncTask简介
- AsyncTask使用简介
- AsyncTask使用简介
- AsyncTask简介与使用
- AsyncTask简介及使用
- AsyncTask使用简介
- Android之AsyncTask异步加载的简介(一)
- 松哥推荐的nginx配置教程
- 8VC Venture Cup 2016 - Elimination Round总结
- C++之 构造函数调用规则
- VBA单元格拷贝
- [NOIP 2010] 引水入城
- Android线程一、AsyncTask使用简介
- UVA1428 Ping pong(树状数组)
- hrbust 1216/哈理工oj 1216 数的划分【dp】
- 笔记:Deep multi patch aggregation network for image style, aesthetics and quality estimation
- Linux应用程序地址布局
- Spark MLlib 1.6 -- 分类和回归篇
- 算法竞赛入门经典 孪生素数
- ThinkPHP框架总结之安全及使用
- 四维超体运动在三维空间的表现1(使用three.js)