详解android中图片的三级缓存及实例
为什么要使用三级缓存
什么是三级缓存
三级缓存原理
具体实现及代码
1. 自定义的图片缓存工具类(mybitmaputils)
通过new mybitmaputils().display(imageview ivpic, string url) 提供给外部方法进行图片缓存的接口
参数含义:ivpic 用于显示图片的imageview,url 获取图片的网络地址
/** * 自定义的bitmaputils,实现三级缓存 */ public class mybitmaputils { private netcacheutils mnetcacheutils; private localcacheutils mlocalcacheutils; private memorycacheutils mmemorycacheutils; public mybitmaputils(){ mmemorycacheutils=new memorycacheutils(); mlocalcacheutils=new localcacheutils(); mnetcacheutils=new netcacheutils(mlocalcacheutils,mmemorycacheutils); } public void display(imageview ivpic, string url) { ivpic.setimageresource(r.mipmap.pic_item_list_default); bitmap bitmap; //内存缓存 bitmap=mmemorycacheutils.getbitmapfrommemory(url); if (bitmap!=null){ ivpic.setimagebitmap(bitmap); system.out.println("从内存获取图片啦....."); return; } //本地缓存 bitmap = mlocalcacheutils.getbitmapfromlocal(url); if(bitmap !=null){ ivpic.setimagebitmap(bitmap); system.out.println("从本地获取图片啦....."); //从本地获取图片后,保存至内存中 mmemorycacheutils.setbitmaptomemory(url,bitmap); return; } //网络缓存 mnetcacheutils.getbitmapfromnet(ivpic,url); } }
2. 网络缓存(netcacheutils)
/** * 三级缓存之网络缓存 */ public class netcacheutils { private localcacheutils mlocalcacheutils; private memorycacheutils mmemorycacheutils; public netcacheutils(localcacheutils localcacheutils, memorycacheutils memorycacheutils) { mlocalcacheutils = localcacheutils; mmemorycacheutils = memorycacheutils; } /** * 从网络下载图片 * @param ivpic 显示图片的imageview * @param url 下载图片的网络地址 */ public void getbitmapfromnet(imageview ivpic, string url) { new bitmaptask().execute(ivpic, url);//启动asynctask } /** * asynctask就是对handler和线程池的封装 * 第一个泛型:参数类型 * 第二个泛型:更新进度的泛型 * 第三个泛型:onpostexecute的返回结果 */ class bitmaptask extends asynctask<object, void, bitmap> { private imageview ivpic; private string url; /** * 后台耗时操作,存在于子线程中 * @param params * @return */ @override protected bitmap doinbackground(object[] params) { ivpic = (imageview) params[0]; url = (string) params[1]; return downloadbitmap(url); } /** * 更新进度,在主线程中 * @param values */ @override protected void onprogressupdate(void[] values) { super.onprogressupdate(values); } /** * 耗时方法结束后执行该方法,主线程中 * @param result */ @override protected void onpostexecute(bitmap result) { if (result != null) { ivpic.setimagebitmap(result); system.out.println("从网络缓存图片啦....."); //从网络获取图片后,保存至本地缓存 mlocalcacheutils.setbitmaptolocal(url, result); //保存至内存中 mmemorycacheutils.setbitmaptomemory(url, result); } } } /** * 网络下载图片 * @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"); int responsecode = conn.getresponsecode(); if (responsecode == 200) { //图片压缩 bitmapfactory.options options = new bitmapfactory.options(); options.insamplesize=2;//宽高压缩为原来的1/2 options.inpreferredconfig=bitmap.config.argb_4444; bitmap bitmap = bitmapfactory.decodestream(conn.getinputstream(),null,options); return bitmap; } } catch (ioexception e) { e.printstacktrace(); } finally { conn.disconnect(); } return null; } }
3. 本地缓存(localcacheutils)
/** * 三级缓存之本地缓存 */ public class localcacheutils { private static final string cache_path= environment.getexternalstoragedirectory().getabsolutepath()+"/werbnews"; /** * 从本地读取图片 * @param url */ public bitmap getbitmapfromlocal(string url){ string filename = null;//把图片的url当做文件名,并进行md5加密 try { filename = md5encoder.encode(url); file file=new file(cache_path,filename); bitmap bitmap = bitmapfactory.decodestream(new fileinputstream(file)); return bitmap; } catch (exception e) { e.printstacktrace(); } return null; } /** * 从网络获取图片后,保存至本地缓存 * @param url * @param bitmap */ public void setbitmaptolocal(string url,bitmap bitmap){ try { string filename = md5encoder.encode(url);//把图片的url当做文件名,并进行md5加密 file file=new file(cache_path,filename); //通过得到文件的父文件,判断父文件是否存在 file parentfile = file.getparentfile(); if (!parentfile.exists()){ parentfile.mkdirs(); } //把图片保存至本地 bitmap.compress(bitmap.compressformat.jpeg,100,new fileoutputstream(file)); } catch (exception e) { e.printstacktrace(); } } }
4. 内存缓存(memorycacheutils)
单色图:每个像素占用1/8个字节,16色图:每个像素占用1/2个字节,256色图:每个像素占用1个字节,24位图:每个像素占用3个字节(常见的rgb构成的图片)
例如一张1920x1080的jpg图片,在android 系统中是以argb格式解析的,即一个像素需占用4个字节,图片的大小=1920x1080x4=7m
实现方法:
/** * 三级缓存之内存缓存 */ public class memorycacheutils { // private hashmap<string,bitmap> mmemorycache=new hashmap<>();//1.因为强引用,容易造成内存溢出,所以考虑使用下面弱引用的方法 // private hashmap<string, softreference<bitmap>> mmemorycache = new hashmap<>();//2.因为在android2.3+后,系统会优先考虑回收弱引用对象,官方提出使用lrucache private lrucache<string,bitmap> mmemorycache; public memorycacheutils(){ long maxmemory = runtime.getruntime().maxmemory()/8;//得到手机最大允许内存的1/8,即超过指定内存,则开始回收 //需要传入允许的内存最大值,虚拟机默认内存16m,真机不一定相同 mmemorycache=new lrucache<string,bitmap>((int) maxmemory){ //用于计算每个条目的大小 @override protected int sizeof(string key, bitmap value) { int bytecount = value.getbytecount(); return bytecount; } }; } /** * 从内存中读图片 * @param url */ public bitmap getbitmapfrommemory(string url) { //bitmap bitmap = mmemorycache.get(url);//1.强引用方法 /*2.弱引用方法 softreference<bitmap> bitmapsoftreference = mmemorycache.get(url); if (bitmapsoftreference != null) { bitmap bitmap = bitmapsoftreference.get(); return bitmap; } */ bitmap bitmap = mmemorycache.get(url); return bitmap; } /** * 往内存中写图片 * @param url * @param bitmap */ public void setbitmaptomemory(string url, bitmap bitmap) { //mmemorycache.put(url, bitmap);//1.强引用方法 /*2.弱引用方法 mmemorycache.put(url, new softreference<>(bitmap)); */ mmemorycache.put(url,bitmap); } }
如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
如对本文有疑问, 点击进行留言回复!!
android RecyclerView checkbox复用解决
Android Q Input (1) -- InputManagerService启动
android -- ndk (stack corruption detected)
网友评论