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); } }
相关文章推荐
- [转] Android 命名规范 (提高代码可以读性)
- TouchEvent、dispatchTouch、onInterceptTouchEvent之间的关系概述
- Android 图片缓冲的管理-内存缓存
- android HAL接口的编码小结
- Android开发学习解决程序运行就出错的一个问题
- android 中的 ContentObserver (一)
- AndroidStudio中使用Git发布与更新,同步到本地(github关联)
- Android TextView内容居中和控件居中
- Android 5.1 Contacts源码分析(一):Contacts模块文件结构
- Android深入浅出之Binder机制
- 关于android自带的图片压缩
- 【Android】 从头搭建视频播放器(5)——将所有放在一起
- android签名
- 基于Html5的android开发
- Android下屏幕适配
- 在android布局中使用layout_weight的几点技巧和说明layout_weight
- 【Android】 从头搭建视频播放器(4)——屏幕旋转处理
- android的WindowManager.addView弹窗添加
- android-support-v7 问题 解决
- android bitmap 平铺