1.图片的三级缓存策略
1.内存缓存:优先加载,速度最快
2.本地缓存:次优先级加载,速度次之,
3.网络缓存:最后加载,速度由网速决定
2.内存缓存
首先创建一个MemoryCacheUtils类,内存缓存一般使用LruChche缓存策略,首先需要或者应用可用的最大内存,然后设置缓存的可用大小,将图片的缓存大小设为最大缓存的1/8或者1/4,应在初始化中调用,因此
public MemoryCacheUtils(){
long maxMemory = Runtime.getRuntime().maxMemory();//获取最大内存,一般默认是16MB
//获取图片字节数
mLruCache = new LruCache((int)maxMemory/8){
@Override
protected int sizeOf(String key, Bitmap value) {
//获取图片字节数
int byteCount = value.getRowBytes() * value.getWidth();
return byteCount;
}
};
}
内存缓存中对图片的保存和读取十分简单
//从内存中获取图片
public Bitmap getBitmapFormMemory(String url){
return mLruCache.get(url);
}
//将图片保存在内存中
public void saveBitmap2Memory(String url, Bitmap bitmap){
mLruCache.put(url, bitmap);
}
3.本地缓存
本地缓存首先需要获取SD卡的根目录的路径
public static final String CACHE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath()+"/imagememory/";
图片的保存
首先以Url作为关键字对图片进行保存,在保存时需要对Url进行MD5加密,将加密后返回的字符串作为关键字创建文件夹,同时保存图片
public void saveBitmap2SD(String url, Bitmap bitmap){
//对文件地址进行MD5加密
String fileName = null;
try {
fileName = MD5Encoder.encode(url);
} catch (Exception e) {
e.printStackTrace();
}
File file = new File(CACHE_PATH, fileName);
File parentFile = file.getParentFile();
if (!parentFile.exists()){
parentFile.mkdirs();
}
try {
//将图片保存到本地
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(file));
} catch (FileNotFoundException e){
e.printStackTrace();
}
}
图片的读取
从SD卡中读取图片,首先也需要将传入的Url进行加密并将返回的字符串作为索引,查找对应的文件夹中,通过BitmapFactory.decodeStream获得bitmap
public Bitmap getImageFormSD(String url){
//对文件地址进行MD5加密
String fileName = null;
try {
fileName = MD5Encoder.encode(url);
} catch (Exception e) {
e.printStackTrace();
}
File file = new File(CACHE_PATH, fileName);
if (file.exists()){
Bitmap bitmap;
try {
bitmap = BitmapFactory.decodeStream(new FileInputStream(file));
return bitmap;
} catch (FileNotFoundException e){
e.printStackTrace();
}
}
return null;
}
4.网络缓存图片
网络缓存图片时需要将网络获得的图片缓存到内存和SD卡中,因此需要在构造方法中初始化内存缓存工具类和SD卡缓存工具类
public NetCacheUtils(SDcardCacheUtils sDcardCacheUtils, MemoryCacheUtils memoryCacheUtils){
mSDcardCacheUtils = sDcardCacheUtils;
mMemoryCacheUtils = memoryCacheUtils;
}
从网络中获取图片是一个耗时操作,因此这里采用AsyncTask异步栈的方式实现图片的异步下载,因此就需要自定义一个MyAsyncTask继承与AsyncTask
class MyAsyncTask extends AsyncTask{
@Override
protected Bitmap doInBackground(Object... objects) {
//拿到传入的iamge
mImageView = (ImageView)objects[0];
mUrl = (String)objects[1];
mImageView.setTag(mUrl);
Bitmap bitmap = downloadBitmap(mUrl);
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if (bitmap != null){
String url = (String) mImageView.getTag();
if (url.equals(mUrl)){
mImageView.setImageBitmap(bitmap);
mMemoryCacheUtils.saveBitmap2Memory(url, bitmap);
mSDcardCacheUtils.saveBitmap2SD(url, bitmap);
}
}
}
}
private Bitmap downloadBitmap(String url) {
HttpURLConnection connection = null;
try {
connection = (HttpURLConnection) new URL(url).openConnection();
connection.setReadTimeout(5000);
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
connection.connect();
int code = connection.getResponseCode();
if (code == 200){
InputStream inputStream = connection.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
return bitmap;
}
} catch (IOException e){
e.printStackTrace();
} finally {
connection.disconnect();
}
return null;
}
5.大图片的加载
1.首先需要拿到位图的尺寸后,进行放缩后再加载位图
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream();
int imageWidth = options.outWidth;
int iamgeHight = options.outHeight;
String imageType = options.outMimeType;
2.计算inSampleSize
public static int calculateInSampleZSize(BitmapFactory.Options options, int reqWidth, int reqHeight){
int width = options.outWidth;
int height = options.outHeight;
int inSampleSize = 1;
if (height>reqHeight || width>reqWidth){
int halfHeight = height / 2;
int halfWidth = width / 2;
while ((halfHeight/inSampleSize)>reqHeight && (halfWidth/inSampleSize)>reqWidth){
inSampleSize *= 2;
}
}
return inSampleSize;
}
3.放缩后再加载小位图
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resid, int reqWidth, int reqHeight){
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res,resid, options);
options.inSampleSize = calculateInSampleZSize(options,reqWidth, reqHeight);
options.inJustDecodeBounds= false;
return BitmapFactory.decodeResource(res,resid,options);
}