Android:AsyncTask -- 异步任务
2015-09-09 11:31
495 查看
概述
Android 中只有主线程可以操作 ui,以保证 ui 的稳定性,而 Android 是多线程的操作系统,像读取文件、网络操作等耗时较长的操作应该放到子线程中执行,以免阻塞主线程。利用 AsyncTask 可方便的实现异步操作,既可以在子线程中执行异步操作,又可以更新 ui。
AsyncTask<Params, Progress, Result>是一个抽象类,用于被继承以实现自定义的异步任务。
继承 AsyncTask 需要指定三个参数类型:
Params:启动任务时输入参数的类型。
Progress:后台任务执行中返回进度值的类型。
Result:后台执行任务完成后返回结果的类型。
AsyncTask 通常需要重写的方法有四个:
onPreExecute:执行后台耗时操作前被调用,通常用于完成一些初始化操作。运行在主线程。
doInBackground:必须重写。异步执行后台线程将要完成的任务。
onProgressUpdate:在doInBackground方法中调用publishProgress方法时调用,用于更新进度。运行在主线程。
onPostExecute:当doInBackground完成后,系统会将doInBackground的返回值传入该方法,以进行后续操作。运行在主线程。
例子:加载网络图片
activity_load_image.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/image"/> <ProgressBar android:visibility="gone" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:id="@+id/progressbar"/> </RelativeLayout>
LoadImageActivity.java
public class LoadImageActivity extends Activity { /** * 网络图片的地址 */ private static final String URL = "http://imgsrc.baidu.com/forum/w=580/sign=57ae714ad2160924dc25a213e407359b/8a82b9014a90f60392de8a5b3b12b31bb051ed44.jpg"; private ImageView imageView; private ProgressBar progressBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_load_image); imageView = (ImageView) findViewById(R.id.image); progressBar = (ProgressBar) findViewById(R.id.progressbar); //启动异步任务 new LoadImageAsyncTask().execute(URL); } class LoadImageAsyncTask extends AsyncTask<String, Void, Bitmap> { /** * 异步任务的准备工作(运行在ui线程) */ @Override protected void onPreExecute() { super.onPreExecute(); //显示进度条 progressBar.setVisibility(View.VISIBLE); } /** * 异步任务(运行在异步线程) * @param strings * @return */ @Override protected Bitmap doInBackground(String... strings) { String url = strings[0]; Bitmap bitmap = null; if (url != null && url.isEmpty() == false) { //下载网络图片,转换为Bitmap URLConnection urlConnection = null; InputStream is = null; try { urlConnection = new URL(url).openConnection(); is = urlConnection.getInputStream(); BufferedInputStream bis = new BufferedInputStream(is); bitmap = BitmapFactory.decodeStream(bis); is.close(); bis.close(); } catch (IOException e) { e.printStackTrace(); } } return bitmap; } /** * 异步任务的结果处理(运行在ui线程) * @param bitmap */ @Override protected void onPostExecute(Bitmap bitmap) { super.onPostExecute(bitmap); //隐藏进度条 progressBar.setVisibility(View.GONE); //显示图片 if (bitmap != null) { imageView.setImageBitmap(bitmap); } } } }
AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
例子:更新进度条 & 取消异步任务
activity_load_progressbar.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp"> <ProgressBar android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" android:id="@+id/progressbar" style="?android:attr/progressBarStyleHorizontal"/> </RelativeLayout>
LoadProgressbarActivity.java
public class LoadProgressbarActivity extends Activity { private ProgressBar progressBar; private LoadProgressbarAsyncTask asyncTask; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_load_progressbar); progressBar = (ProgressBar) findViewById(R.id.progressbar); asyncTask = new LoadProgressbarAsyncTask(); asyncTask.execute(); } @Override protected void onPause() { if (asyncTask != null && asyncTask.getStatus() == AsyncTask.Status.RUNNING) { //标记为取消状态,否则在退出activity再进入activity时,要等待前一个任务执行完成才会开始执行 asyncTask.cancel(true); } super.onPause(); } class LoadProgressbarAsyncTask extends AsyncTask<Void, Integer, Void> { @Override protected Void doInBackground(Void... voids) { for (int i=0; i<100; i++) { //判断若已取消,则停止 if (isCancelled()) { break; } try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } //更新进度 publishProgress(i); } return null; } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); if (isCancelled()) { return; } //更新进度条 progressBar.setProgress(values[0]); } } }
AsyncTask 注意事项
必须在 ui 线程中创建 AsyncTask 的实例。必须在 ui 线程中调用 execute 方法。
重写的四个方法是系统自动调用的,不应手动调用。
每个 AsyncTask 只能被执行一次,多次调用会引发异常。
doInBackground 中不能直接更新 ui。
参考:http://www.imooc.com/learn/377
相关文章推荐
- android 限制广播消息的接收者
- Android的BUG(三) - 广为人知的诟病:频繁重启问题
- android数据库——GreenDao
- Android 四大组件之一:Service后台服务之IntentService
- android listview每个item定义动画呈现
- Android 隐藏LinearLayout
- android 资源之 color
- Android:自定义View实现水波进度效果
- Android控件之GridView用法实例分析
- 调取手机设置模式里的震动或铃声 Android
- Android 组件安全
- Android studio如何使用SVN进行版本控制
- android style的继承方式 点(.)和parent
- Android 5.0以上除去标题栏
- Android中visibility属性VISIBLE、INVISIBLE、GONE的区别
- android中context的使用
- Leo仿【DOTA视频站】项目实践【五】---- fragment中嵌套viewpage、fragment实现从优酷中下载视频
- Android ViewSwitcher简介和使用
- 详解:android- monkey命令
- Android(java)学习笔记217:开发一个多界面的应用程序之清单文件