您的位置:首页 > 移动开发 > Android开发

Android ListView&异步加载的学习(三)——AsyncTask加载图片&运用Lru算法优化图片加载

2015-08-06 20:17 489 查看
----新建showImageByAsyncTask()方法,新建一个NewsAsyncTask类继承AsyncTask类,实现类方法doInBackGround()和onPostExecue(),通过doInBackground()方法从url返回Bitmap,通过onPostExecue()方法将Bitmap传递给ImageView;在showImageByAsyncTask()方法中调用AsyncTask:

public void showImageByAsyncTask(ImageView imageView,String url){//调用AsyncTask
new NewsAsyncTask(imageView, url).execute(url);
}
class NewsAsyncTask extends AsyncTask<String,Void,Bitmap>{
private ImageView mImageView;
public NewsAsyncTask(ImageView imageView){
mImageView = imageView;
}
@Override
protected Bitmap doInBackground(String... params) {
return getBitmapFromURL(params[0]);
}
@Override
protected void onPostExecute(Bitmap bitmap) {//将Bitmap传递给ImageView
super.onPostExecute(bitmap);
mImageView.setImageBitmap(bitmap);
}
}


以上实现图片加载的功能。

</pre><pre>

但是发现AsyncTask和多线程存在相同的图片加载时序问题,需要进行完善:

----在NewsAsyncTask类中声明一个string类型的url来接收传进来的url,在将Bitmap传递给ImageView时进行判断,只有ImageView.getTag.equals(url)时才进行传递:

protected void onPostExecute(Bitmap bitmap) {//将Bitmap传递给ImageView
super.onPostExecute(bitmap);
if (mImageView.getTag().equals(mUrl)) {
mImageView.setImageBitmap(bitmap);
}
}
以上完成图片加载的时序问题。

但是考虑到每次上下滑动ListView时,由于ListView的缓存特性,需要对滑出屏幕显示窗口的图片进行重新加载,这一举动会消耗掉很多流量来加载图片,同时在手机网速不好时ListView的滑动并不流畅,带来很不好的用户体验。因此需要进行进一步优化,使用缓存方法将加载过的图片进行缓存。

思想如下:

运用到Lru算法,即Least Resently Used,近期最少使用算法。

Android提供LruCache类来实现Lru算法,将内容缓存在内存中并以一定方法管理这些内容,将近期最少使用的内容从内存中剔除。

以下实现LruCache缓存:

----创建Cache:在ImageLoader中声明LruCache成员变量,LruCache<传入数据类型,传出数据类型>,此处显然传入的数据url为String类型,传出Bitmap

----初始化cache:通过写这个java文件的ImageLoader类的构造方法来初始化,需要获取最大内存,同时在每次存入缓存时调用cache的sizeOf方法告诉缓存当前存入的对象的大小:

public ImageLoader(){
//获取最大可用内存
int maxMemory= (int) Runtime.getRuntime().maxMemory();
int cacheSize=maxMemory/4;
mCaches=new LruCache<String,Bitmap>(cacheSize){
@Override
protected int sizeOf(String key, Bitmap value) {
//每次存入缓存的时候调用
return value.getByteCount();
}
};
}
----使用cache:通过两个函数来讲图片存入缓存、从缓存中读取数据

public void addBitmapToCache(String url,Bitmap bitmap){
if (getBitmapFromCache(url)==null){//判断是否已经存入缓存
mCaches.put(url,bitmap);
}
}

public Bitmap getBitmapFromCache(String url){
return mCaches.get(url);
}
修改showImageByAsyncTask方法来完善AsyncTask的调用,声明一个Bitmap变量来保存从cache中获取的数据,进行判断,若获取到的数据不存在于缓存中,则只能进行创建,否则只需要将从cache中获取的bitmap传递给imageView:

public void showImageByAsyncTask(ImageView imageView,String url){//调用AsyncTask
Bitmap bitmap=getBitmapFromCache(url);
if(bitmap==null) {
new NewsAsyncTask(imageView, url).execute(url);
}else{
imageView.setImageBitmap(bitmap);
}
}
修改实现AsyncTask缓存机制的doInBackground方法,使从网络中下载的图片保存入cache中:

protected Bitmap doInBackground(String... params) {
Bitmap bitmap=getBitmapFromUrl(params[0]);
if (bitmap!=null){
addBitmapToCache(params[0],bitmap);
}
return bitmap;
}
以上实现了LruCache从创建到功能的实现,但是由于运用到了cache就不能使用原先适配器中showImageByAsyncTask()方法将url传递给ImageView,否则将会导致每次调用显示图片的方法都会创建一个cache:

在Adapter类中声明一个ImageLoader类对象,并在Adapter的构造方法中进行初始化:mImageLoader=new ImageLoader();

由此将图片的url传递给ImageView的方式也需要修改,在ListView缓存机制中若view存在则不需要新建一个ImageLoader类对象来加载图片,只需要调用cache中已经加载好的图片:mImageLoader.showImageByAsyncTask(viewHolder.ivIcon,mList.get(position).newsIconURL);

以上运用Cache完善了图片加载,使向下滑动初次加载完图片后再向上滑动加载图片时,不需要重新加载,只需要从cache中调用即可,节省了用户加载图片消耗的时间以及数据流量。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: