详解Android 图片的三级缓存及图片压缩
程序员文章站
2024-02-26 14:27:34
为什么需要图片缓存
android默认给每个应用只分配16m的内存,所以如果加载过多的图片,为了防止内存溢出,应该将图片缓存起来。图片的三级缓存分别是:
内存缓...
为什么需要图片缓存
android默认给每个应用只分配16m的内存,所以如果加载过多的图片,为了防止内存溢出,应该将图片缓存起来。图片的三级缓存分别是:
- 内存缓存
- 本地缓存
- 网络缓存
其中,内存缓存应优先加载,它速度最快;本地缓存次优先加载,它速度也快;网络缓存不应该优先加载,它走网络,速度慢且耗流量。
三级缓存的具体实现
网络缓存
- 根据图片的url去加载图片
- 在本地和内存中缓存
public class netcacheutils { private localcacheutils mlocalcacheutils; private memorycacheutils mmemorycacheutils; public netcacheutils(localcacheutils localcacheutils, memorycacheutils memorycacheutils) { mlocalcacheutils = localcacheutils; mmemorycacheutils = memorycacheutils; } /** * 从网络下载图片 * * @param ivpic * @param url */ public void getbitmapfromnet(imageview ivpic, string url) { new bitmaptask().execute(ivpic, url);// 启动asynctask, // 参数会在doinbackground中获取 } /** * handler和线程池的封装 * * 第一个泛型: 参数类型 第二个泛型: 更新进度的泛型, 第三个泛型是onpostexecute的返回结果 * * */ class bitmaptask extends asynctask<object, void, bitmap> { private imageview ivpic; private string url; /** * 后台耗时方法在此执行, 子线程 */ @override protected bitmap doinbackground(object... params) { ivpic = (imageview) params[0]; url = (string) params[1]; ivpic.settag(url);// 将url和imageview绑定 return downloadbitmap(url); } /** * 更新进度, 主线程 */ @override protected void onprogressupdate(void... values) { super.onprogressupdate(values); } /** * 耗时方法结束后,执行该方法, 主线程 */ @override protected void onpostexecute(bitmap result) { if (result != null) { string bindurl = (string) ivpic.gettag(); if (url.equals(bindurl)) {// 确保图片设定给了正确的imageview ivpic.setimagebitmap(result); mlocalcacheutils.setbitmaptolocal(url, result);// 将图片保存在本地 mmemorycacheutils.setbitmaptomemory(url, result);// 将图片保存在内存 system.out.println("从网络缓存读取图片啦..."); } } } } /** * 下载图片 * * @param url * @return */ private bitmap downloadbitmap(string url) { httpurlconnection conn = null; try { conn = (httpurlconnection) new url(url).openconnection(); conn.setconnecttimeout(5000); conn.setreadtimeout(5000); conn.setrequestmethod("get"); conn.connect(); int responsecode = conn.getresponsecode(); if (responsecode == 200) { inputstream inputstream = conn.getinputstream(); //图片压缩处理 bitmapfactory.options option = new bitmapfactory.options(); option.insamplesize = 2;//宽高都压缩为原来的二分之一, 此参数需要根据图片要展示的大小来确定 option.inpreferredconfig = bitmap.config.rgb_565;//设置图片格式 bitmap bitmap = bitmapfactory.decodestream(inputstream, null, option); return bitmap; } } catch (exception e) { e.printstacktrace(); } finally { conn.disconnect(); } return null; } }
本地缓存
两个方法:设置本地缓存,获取本地缓存
public class localcacheutils { public static final string cache_path = environment .getexternalstoragedirectory().getabsolutepath() + "/local_cache"; /** * 从本地sdcard读图片 */ public bitmap getbitmapfromlocal(string url) { try { string filename = md5encoder.encode(url); file file = new file(cache_path, filename); if (file.exists()) { bitmap bitmap = bitmapfactory.decodestream(new fileinputstream( file)); return bitmap; } } catch (exception e) { e.printstacktrace(); } return null; } /** * 向sdcard写图片 * * @param url * @param bitmap */ public void setbitmaptolocal(string url, bitmap bitmap) { try { string filename = md5encoder.encode(url); file file = new file(cache_path, filename); file parentfile = file.getparentfile(); if (!parentfile.exists()) {// 如果文件夹不存在, 创建文件夹 parentfile.mkdirs(); } // 将图片保存在本地 bitmap.compress(compressformat.jpeg, 100, new fileoutputstream(file)); } catch (exception e) { e.printstacktrace(); } } }
内存缓存
两个方法:设置内存缓存,获取内存缓存
问题:
如果使用hashmap存储图片时,当图片越来越多时,会导致内存溢出,因为它是强引用,java的垃圾回收器不会回收。
如若改成软引用softreference(内存不够时,垃圾回收器会考虑回收),仍有一个问题:在android2.3+, 系统会优先将softreference的对象提前回收掉, 即使内存够用。
解决办法:可以用lrucache来解决上述内存不回收或提前回收的问题。least recentlly use 最少最近使用算法 它会将内存控制在一定的大小内, 超出最大值时会自动回收, 这个最大值开发者自己定
public class memorycacheutils { // private hashmap<string, softreference<bitmap>> mmemorycache = new // hashmap<string, softreference<bitmap>>(); private lrucache<string, bitmap> mmemorycache; public memorycacheutils() { long maxmemory = runtime.getruntime().maxmemory() / 8;// 模拟器默认是16m mmemorycache = new lrucache<string, bitmap>((int) maxmemory) { @override protected int sizeof(string key, bitmap value) { int bytecount = value.getrowbytes() * value.getheight();// 获取图片占用内存大小 return bytecount; } }; } /** * 从内存读 * * @param url */ public bitmap getbitmapfrommemory(string url) { // softreference<bitmap> softreference = mmemorycache.get(url); // if (softreference != null) { // bitmap bitmap = softreference.get(); // return bitmap; // } return mmemorycache.get(url); } /** * 写内存 * * @param url * @param bitmap */ public void setbitmaptomemory(string url, bitmap bitmap) { // softreference<bitmap> softreference = new // softreference<bitmap>(bitmap); // mmemorycache.put(url, softreference); mmemorycache.put(url, bitmap); } }
图片压缩
//图片压缩处理(在从网络获取图片的时候就进行压缩) bitmapfactory.options option = new bitmapfactory.options(); option.insamplesize = 2;//宽高都压缩为原来的二分之一, 此参数需要根据图片要展示的大小来确定 option.inpreferredconfig = bitmap.config.rgb_565;//设置图片格式 bitmap bitmap = bitmapfactory.decodestream(inputstream, null, option);
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。