今天在项目里面用到了listview的三级缓存 涉及图片的网络加载和后续的内存存储和本地文件存储 这样可以减少用户的流量和加快访问图片的速度 本例子里面主要是设计LruCache,对于DiskLruCache下次我会写出来的 .
LruCache(Least Recently Used)缓存的算法,即是近期最少使用算法,该算法的核心就是当缓存满的时候就会优先淘汰掉那些近期最少使用的缓存对象.
<span style="font-size:18px;">import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.example.wisdombj.MainActivity;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.support.v4.util.LruCache;
import android.widget.ImageView;
/**
* 实现listview的三级缓存 主要就是 内存 文件 和 网络
* 此外在实现三级缓存的时候还是要注意到 防止listview滑动速度过快造成图片的加载误差的出现
* 1.要注意在首次从网络上面加载图片的时候要将图片的数据存放到内存缓存和本地文件里面
* 2.因为在网络上面加载图片的时候需要多个线程同时开启 这个时候就需要开启线程池进行线程的分配
* 3.标记每个控件的URL,防止加载图片的混乱
* 4.存放在本地的文件 URL地址要进行安全的加密
*
* @author xiaojiang
*
*/
public class BitmapCacheUtils {
//本地文件地址
private File mCacheImageFile;
//上下文
private MainActivity mMainActivity;
//线程池
private ExecutorService mNewFixedThreadPool;
// 保留最后一次访问URL的信息
private Map<ImageView, String> mUrlImageData = new HashMap<ImageView, String>();
//通过LruCache算法进行图片的缓存
private LruCache<String, Bitmap> mLruCache = new LruCache<String, Bitmap>(
(int) (Runtime.getRuntime().freeMemory() / 4)) {
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}
};
public BitmapCacheUtils(MainActivity main) {
mMainActivity = main;
mCacheImageFile = new File(main.getCacheDir(), "images");
//此处线程池里面的 6 是根据具体的APP设备的listview的标准的界面展示的个数进行输入的
mNewFixedThreadPool = Executors.newFixedThreadPool(6);
}
/**
* 向imageview上面添加图片
* @param imgView
* @param url
*/
public void display(ImageView imgView, String url) {
// 1.从内存里面获取相应的图片
Bitmap bitmap = mLruCache.get(url);
if (bitmap != null) {
imgView.setImageBitmap(bitmap);
return;
}
// 2.从本地APP目录里面获取到相应的图片
bitmap = getBitmapFromFile(url);
if (bitmap != null) {
imgView.setImageBitmap(bitmap);
return;
}
//存放控件对应的url信息 防止快速滑动listview的时候加载控件的图片的混乱
//后续的控件的加载的图片的URL要是跟map里面的URL不匹配就会将这个URL改掉换成最新的URL地址
mUrlImageData.put(imgView, url);
// 3.从网络上面获取到相应的图片
getBitmapFromNet(imgView, url);
}
/**
* 从线程池里面获取线程从网络上面下载图片
* @param imgView
* @param url
*/
private void getBitmapFromNet(ImageView imgView, String url) {
mNewFixedThreadPool.submit(new Download(url, imgView));
}
private class Download implements Runnable {
private String url;
private ImageView imgView;
public Download(String url, ImageView imgView) {
this.url = url;
this.imgView = imgView;
}
@Override
public void run() {
try {
URL urlImg = new URL(url);
HttpURLConnection connection = (HttpURLConnection) urlImg.openConnection();
connection.setConnectTimeout(6000);
connection.setRequestMethod("GET");
if (connection.getResponseCode() == 200) {
InputStream stream = connection.getInputStream();
final Bitmap bitmapStream = BitmapFactory.decodeStream(stream);
// 向内存里面存放图片
mLruCache.put(url, bitmapStream);
// 向本地的文件里面存放图片
saveBitmap2File(bitmapStream, Md5Utils.md5(url));
// 显示图片
mMainActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
// 判断URL是不是最新的URL true就是最新的数据(进行显示)
// false就是过去的数据(不进行显示)
if (url.equals(mUrlImageData.get(imgView))) {
imgView.setImageBitmap(bitmapStream);
}
}
});
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 向文件里面存放图片数据
*
* @param bitmap
* @param url
*/
private void saveBitmap2File(Bitmap bitmap, String url) {
File imgCacheFile = new File(mCacheImageFile, url);
try {
//压缩图片
bitmap.compress(CompressFormat.JPEG, 100, new FileOutputStream(imgCacheFile));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
/**
* 从文件里获取图片
* @param url
* @return
*/
private Bitmap getBitmapFromFile(String url) {
File imgCacheFile = new File(mCacheImageFile, Md5Utils.md5(url));
if (imgCacheFile != null && imgCacheFile.exists()) {
Bitmap bitmap = BitmapFactory.decodeFile(imgCacheFile.getAbsolutePath());
mLruCache.put(url, bitmap);
return bitmap;
}
return null;
}
}
</span>