Android异步载入全解析之使用AsyncTask
概述
既然前面提到了多线程,就不得不提到线程池,通过线程池,不仅能够对并发线程进行管理。更能够提高他们运行的效率。优化整个App。当然我们能够自己创建一个线程池。只是这样是非常烦的,要创建一个高效的线程池还是挺费事的,只是,Android系统给我吗提供了AsyncTask这样一个类,来帮助我们高速实现多线程开发,它的底层实现,事实上就是一个线程池。
AsyncTask初探
AsyncTask,顾名思义就是用来做异步处理的。通过AsyncTask。我们能够非常方便的解决多线程。以及多线程之间的通信问题。
AsyncTask參数
抽象类AsyncTask具有三个泛型參数:
AsyncTask <Params, Progress, Result>
- Params: 这个泛型指定的是我们传递给异步任务运行时的參数的类型
- Progress: 这个泛型指定的是我们的异步任务在运行的时候将运行的进度返回给UI线程的參数的类型
- Result: 这个泛型指定的异步任务运行完后返回给UI线程的结果的类型
我们在创建AsyncTask的时候。须要指定这三个參数。
AsyncTask方法
AsyncTask具有这样几个抽象方法:
onPreExecute(): 这种方法是在运行异步任务之前的时候运行,而且是在UI Thread其中运行的。通常我们在这种方法里做一些UI控件的初始化的操作,
比如弹出ProgressDialog
doInBackground(Params... params): 在onPreExecute()方法运行完之后。会立即运行这种方法。这种方法就是来处理异步任务的方法,
Android操作系统会在后台的线程池其中开启一个worker thread来运行我们的这种方法,所以这种方法是在worker thread其中运行的。
这种方法运行完之后就能够将我们的运行结果发送给我们的最后一个 onPostExecute 方法,因此,doInBackground是这四个方法中唯
一必须要重写的方法。在这种方法中,我们能够从网络其中获取数据等一些耗时操作
onProgressUpdate(Progess... values): 这种方法也是在UI Thread其中运行的。我们在异步任务运行的时候,
有时候须要将运行的进度返回给我们的UI界面。比例如以下载一张网络图片,我们须要时刻显示其下载的进度,
就能够使用这种方法来更新我们的进度。
这种方法在调用之前,我们须要在 doInBackground 方法中
调用一个 publishProgress(Progress) 的方法来将我们的进度时时刻刻传递给 onProgressUpdate 方法从而来更新进度
onPostExecute(Result... result): 当我们的异步任务运行完之后。就会将结果返回给这种方法,这种方法也是在UI Thread其中调用的,
我们能够将返回的结果显示在UI控件上
AsyncTask使用
如今回到我们的样例中,我们利用AsyncTask来下载图像,当然。下载图像的方法还是使用那个getBitmapFromUrl()方法。首先。我们先写一个ASyncDownloadImage类,继承AsyncTask:
private class ASyncDownloadImage extends AsyncTask<String, Void, Bitmap> { private ImageView imageView;
private String url; public ASyncDownloadImage(ImageView imageView, String url) {
this.imageView = imageView;
this.url = url;
} @Override
protected Bitmap doInBackground(String... params) {
return getBitmapFromUrl(params[0]);
} @Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
if (imageView.getTag().equals(url)) {
imageView.setImageBitmap(bitmap);
}
}
}
这个AsyncTask我们重写了doInBackground用来异步下载图像,重写了onPostExecute来将图像设置到ImageView上。
因此。我们将AsyncTask的三个泛型參数设置为:
AsyncTask<String, Void, Bitmap>
即參数类型为String——url,进度类型——Void 不须要,返回类型——Bitmap 下载的图像。
在设置图像的时候,我们相同须要通过tag来进行推断。
最后,我们与使用多线程一样,创建一个showImageByASync方法,来调用AsyncTask:
/**
* Using ASyncTask
* @param imageView
* @param url
*/
public void showImageByASync(ImageView imageView, String url) {
ASyncDownloadImage task = new ASyncDownloadImage(imageView, url);
task.execute(url);
}
AsyncTask中有几个地方还是须要注意下的:
- execute方法仅仅能在UI线程中调用
- AsyncTask实例也必须在UI线程中创建
- AsyncTask的抽象方法不要手动去调用。系统自己主动会去管理
- AsyncTask仅仅能运行一次
最后,仅仅须要将Adapter中的getView方法的mImageLoader.showImageByThread(viewHolder.imageView, url);改为例如以下所看到的就可以:
mImageLoader.showImageByASync(viewHolder.imageView, url);
最后,显示当然是没有问题,就不贴图了。