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

android 图片的加载保存 与 二级缓存

2015-09-25 20:50 531 查看
// 学习中的一些Demo
/* 需要考虑的内容
* 1.图片的设置用异步任务可能错错位
*  解决方案之一为,设置异步任务的时候,为ImageView 设置一个 tag,内容为图片的唯一标识
*  可以为网址,当回调任务返回时,判断此时的ImageView tag中的网址是否和 任务执行的网址相同,
*  如果不相同,说明复用的ImageView已经被滑走了,这个异步任务不需要给它设置图片了,
* 2.图片的缓存问题,android系统给应用分配的内存并不大,需要考虑图片缓存,考虑常见的二级缓存,
*   需要分别缓存到内存 和 本地存储,adapter在获取图片的时候先去内存中查找,找不到再去本地存储找
**  再找不到才去请求网络,请求网络获得的图片缓存到本地
*
* 3.图片的显示问题, 从网络下载的图片的分辨率可能太大,需要用到 缩小图片的采样,
* 安卓官方有提供相应的方法,使用BitmapFactory.Options 来获取图片的信息,再进行缩小比例的采样,最后才显示
*
* 4.图片的引用问题,如果采用强引用的话,如果Activity已经fininsh()了,而由于 这个任务其实已经不需要设置图片了,
*   而由于采用了强引用,导致Activity不能被GC , 任务继续执行,
*/
public class ImageLoadTask extends AsyncTask<String, Void, Bitmap> {

//使用弱引用包裹ImageView, 支持GC,释放内存之后就不会再设置图片了
// 支持一部分释放操作:Activity结束 ListView销毁
private final WeakReference<View> viewReference;
private String url;

public ImageLoadTask(View view) {
this.viewReference = new WeakReference<View>(view);
}

@Override
protected Bitmap doInBackground(String... params) {

Bitmap ret = null;

if (params != null && params.length > 0) {
url = params[0];

//0 .1  采用2级缓存的做法,先从内存中查找
ImageCache imageCache = ImageCache.getInstance();

Bitmap bitmap = imageCache.get(url);
if (bitmap == null) {//内存缓存不存在
// 1.本地存储的文件缓存,是否存在
byte[] bytes = FileCacheManager.getInstance().load(url);
//本地存储文件不存时,进行网络的加载
if (bytes == null) {
//从网络读取图片字节
bytes = HttpUtil.doGet(url);

//文件缓存到本地
FileCacheManager.getInstance().save(url, bytes);

//                InputStream inputStream = HttpUtil.doGetInputStream(url);
//                if (inputStream != null) {
//                    //todo 处理图片的存储和转换,比起字节数组的方式更好吗?
//                    ret = BitmapFactory.decodeStream(inputStream);
//
//                }

} //文件存在直接解码

//解码字节数组
ret = loadScaledBitmap(bytes, 256, 256);
//!!! 释放内存,字节数组
bytes = null;

//缓存到内存中
imageCache.put(url, ret);
} else {//如果内存缓存存在
ret = bitmap;

}

}
return ret;
}

/**
* 针对图片进行数据进行缩小转换 (二次采样)
*
* @param data
* @param toWidth
* @param toHeight
* @return Bitmap
*/
private static Bitmap loadScaledBitmap(byte[] data, int toWidth, int toHeight) {
Bitmap ret = null;
// 1.获取尺寸 (使用 oOptions 来设置)-> 只获取图片,不生成图片

//Options 用来进行解码的配置,这个对象那不的变量会被传给 底层操作系统的 C代码库
BitmapFactory.Options options = new BitmapFactory.Options();

//该参数为true  表示值进行图片尺寸的获取,不会在decode..方法中返回px的 Bitmap,不占用内存
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(data, 0, data.length, options);

int picWidth = options.outWidth;
int picHeight = options.outHeight;

// 2.缩小图片 (使用 Options 进行缩小的采样)
options.inJustDecodeBounds = false;//设置为false, 将返回真实的Bitmap图片
options.inSampleSize = calculateInSampleSize(options, picWidth, picHeight); //图片采样比例 >= 1(!must),功能:  example,当设置为2是,代表宽度/高度 变为 1/2

options.inPurgeable = true;//绘制后释放内存
options.inPreferredConfig = Bitmap.Config.RGB_565;//降低了一个像素的颜色的字节数

ret = BitmapFactory.decodeByteArray(data, 0, data.length, options);
// 2.缩小图片
return ret;
}

public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;

if (height > reqHeight || width > reqWidth) {

final int halfHeight = height / 2;
final int halfWidth = width / 2;

// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}

return inSampleSize;
}

@Override
protected void onPostExecute(Bitmap bitmap) {
if (bitmap != null && viewReference != null) {
View view = viewReference.get();

if (view != null) {
//TODO    检修是否需要Tag处理错误

Object tag = view.getTag();
boolean match = true;
if (tag != null) {
if (tag instanceof String) {
String str = (String) tag;

match = url.equals(str);

}
}

if (match) {
if (view instanceof ImageView) {
((ImageView) view).setImageBitmap(bitmap);
} else {
view.setBackgroundDrawable(new BitmapDrawable(bitmap));
}
}
}

}

super.onPostExecute(bitmap);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: