图片缓存之内存缓存技术LruCache,软引用
每当碰到一些大图片的时候,我们如果不对图片进行处理就会报OOM异常,
这个问题曾经让我觉得很烦恼,后来终于得到了解决,
那么现在就让我和大家一起分享一下吧。
这篇博文要讲的图片缓存机制,我接触到的有两钟,一种是软引用,另一种是内存缓存技术。
先来看下两者的使用方式,再来作比较。
除了加载图片时要用到缓存处理,还有一个比较重要的步骤要做,就是要先压缩图片。
1、压缩图片
至于要压缩到什么状态就要看自己当时的处境了,压缩图片的时候既要达到一个小的值,又不能让其模糊
,更不能拉伸图片。
- /**
- * 加载内存卡图片
- */
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inJustDecodeBounds = true; // 设置了此属性一定要记得将值设置为false
- Bitmap bitmap = null;
- bitmap = BitmapFactory.decodeFile(url, options);
- int be = (int) ((options.outHeight > options.outWidth ? options.outHeight / 150
- : options.outWidth / 200));
- if (be <= 0) // 判断200是否超过原始图片高度
- be = 1; // 如果超过,则不进行缩放
- options.inSampleSize = be;
- options.inPreferredConfig = Bitmap.Config.ARGB_4444;
- options.inPurgeable = true;
- options.inInputShareable = true;
- options.inJustDecodeBounds = false;
- try {
- bitmap = BitmapFactory.decodeFile(url, options);
- } catch (OutOfMemoryError e) {
- System.gc();
- Log.e(TAG, "OutOfMemoryError");
- }
2、软引用:
只要有足够的内存,就一直保持对象,直到发现内存吃紧且没有Strong
Ref时才回收对象。
我们可以这样定义:map里面的键是用来放图片地址的,既可以是网络上的图片地址,也可以SDcard上的图片地址,
map里面的值里面放的是持有软引用的Bitmap,当然如果你要放Drawable,那也是可以的。
- private Map<String, SoftReference<Bitmap>> imageMap
- = new HashMap<String, SoftReference<Bitmap>>();
接下来就让我再介绍一下如何具体加载图片:
步骤:(1)先通过URL查看缓存中是否有图片,如果有,则直接去缓存中取得。
如果没有,就开线程重新去网上下载。
(2)下载完了之后,就把图片放在缓存里面,方便下次可以直接从缓存中取得。
- public Bitmap loadBitmap(final String imageUrl,final ImageCallBack imageCallBack) {
- SoftReference<Bitmap> reference = imageMap.get(imageUrl);
- if(reference != null) {
- if(reference.get() != null) {
- return reference.get();
- }
- }
- final Handler handler = new Handler() {
- public void handleMessage(final android.os.Message msg) {
- //加入到缓存中
- Bitmap bitmap = (Bitmap)msg.obj;
- imageMap.put(imageUrl, new SoftReference<Bitmap>(bitmap));
- if(imageCallBack != null) {
- imageCallBack.getBitmap(bitmap);
- }
- }
- };
- new Thread(){
- public void run() {
- Message message = handler.obtainMessage();
- message.obj = downloadBitmap(imageUrl);
- handler.sendMessage(message);
- }
- }.start();
- return null ;
- }
- // 从网上下载图片
- private Bitmap downloadBitmap (String imageUrl) {
- Bitmap bitmap = null;
- try {
- bitmap = BitmapFactory.decodeStream(new URL(imageUrl).openStream());
- return bitmap ;
- } catch (Exception e) {
- e.printStackTrace();
- return null;
- }
- }
- public interface ImageCallBack{
- void getBitmap(Bitmap bitmap);
- }
2、内存缓存技术
另外一种图片缓存的方式就是内存缓存技术。在Android中,有一个叫做LruCache类专门用来做图片缓存处理的。
它有一个特点,当缓存的图片达到了预先设定的值的时候,那么近期使用次数最少的图片就会被回收掉。
步骤:(1)要先设置缓存图片的内存大小,我这里设置为手机内存的1/8,
手机内存的获取方式:int MAXMEMONRY = (int) (Runtime.getRuntime() .maxMemory() / 1024);
(2)LruCache里面的键值对分别是URL和对应的图片
(3)重写了一个叫做sizeOf的方法,返回的是图片数量。
- private LruCache<String, Bitmap> mMemoryCache;
- private LruCacheUtils() {
- if (mMemoryCache == null)
- mMemoryCache = new LruCache<String, Bitmap>(
- MAXMEMONRY / 8) {
- @Override
- protected int sizeOf(String key, Bitmap bitmap) {
- // 重写此方法来衡量每张图片的大小,默认返回图片数量。
- return bitmap.getRowBytes() * bitmap.getHeight() / 1024;
- }
- @Override
- protected void entryRemoved(boolean evicted, String key,
- Bitmap oldValue, Bitmap newValue) {
- Log.v("tag", "hard cache is full , push to soft cache");
- }
- };
- }
(4)下面的方法分别是清空缓存、添加图片到缓存、从缓存中取得图片、从缓存中移除。
移除和清除缓存是必须要做的事,因为图片缓存处理不当就会报内存溢出,所以一定要引起注意。
- public void clearCache() {
- if (mMemoryCache != null) {
- if (mMemoryCache.size() > 0) {
- Log.d("CacheUtils",
- "mMemoryCache.size() " + mMemoryCache.size());
- mMemoryCache.evictAll();
- Log.d("CacheUtils", "mMemoryCache.size()" + mMemoryCache.size());
- }
- mMemoryCache = null;
- }
- }
- public synchronized void addBitmapToMemoryCache(String key, Bitmap bitmap) {
- if (mMemoryCache.get(key) == null) {
- if (key != null && bitmap != null)
- mMemoryCache.put(key, bitmap);
- } else
- Log.w(TAG, "the res is aready exits");
- }
- public synchronized Bitmap getBitmapFromMemCache(String key) {
- Bitmap bm = mMemoryCache.get(key);
- if (key != null) {
- return bm;
- }
- return null;
- }
- /**
- * 移除缓存
- *
- * @param key
- */
- public synchronized void removeImageCache(String key) {
- if (key != null) {
- if (mMemoryCache != null) {
- Bitmap bm = mMemoryCache.remove(key);
- if (bm != null)
- bm.recycle();
- }
- }
- }
4、两者的比较
说到这里,我觉得有必要来进行一下比较了。
网上有很多人使用软引用加载图片的多 ,但是现在已经不再推荐使用这种方式了,
(1)因为从 Android 2.3 (API Level 9)开始,垃圾回收器会更倾向于回收持有软引用或弱引用的对象,
这让软引用和弱引用变得不再可靠。
(2)另外,Android 3.0 (API Level 11)中,图片的数据会存储在本地的内存当中,
因而无法用一种可预见的方式将其释放,这就有潜在的风险造成应用程序的内存溢出并崩溃,
所以我这里用得是LruCache来缓存图片,当存储Image的大小大于LruCache设定的值,系统自动释放内存,
这个类是3.1版本中提供的,如果你是在更早的Android版本中开发,则需要导入android-support-v4的jar包。
后记:我一直有强调一件事件,就是人应该要不停地进步,没有人生来就会编码,
更没有人一开始就能找到很好的解决方案,我介绍了这两种用法,其实就是想说,
这些都是我的技术进步的一个历程。如果大家有好的建议或者有什么好的看法,
记得提出来,很高兴能和大家分享。
图片缓存之内存缓存技术LruCache,软引用的更多相关文章
- 图片_ _图片缓存之内存缓存技术LruCache,软引用
每当碰到一些大图片的时候,我们如果不对图片进行处理就会报OOM异常,这个问题曾经让我觉得很烦恼,后来终于得到了解决,那么现在就让我和大家一起分享一下吧.这篇博文要讲的图片缓存机制,我接触到的有两钟,一 ...
- 转 图片缓存之内存缓存技术LruCache,软引用
每当碰到一些大图片的时候,我们如果不对图片进行处理就会报OOM异常,这个问题曾经让我觉得很烦恼,后来终于得到了解决,那么现在就让我和大家一起分享一下吧.这篇博文要讲的图片缓存机制,我接触到的有两钟,一 ...
- android内存优化发展——使用软引用
整个Android开发者一定是遇到了内存溢出这个头疼的问题,一旦这个问题.很难直接决定我们的应用程序是哪里出了问题,为了找到问题的解决方案,必须累积发行通过一些内存分析工具高速定位和强大的体验,现在详 ...
- 【转】图片缓存之内存缓存技术LruCache、软引用 比较
每当碰到一些大图片的时候,我们如果不对图片进行处理就会报OOM异常,这个问题曾经让我觉得很烦恼,后来终于得到了解决,那么现在就让我和大家一起分享一下吧.这篇博文要讲的图片缓存机制,我接触到的有两钟,一 ...
- Android 图片三级缓存之内存缓存(告别软引用(SoftRefrerence)和弱引用(WeakReference))
因为之前项目同事使用了图片三级缓存,今天整理项目的时候发现同事还是使用了软引用(SoftRefrerence)和弱引用(WeakReference),来管理在内存中的缓存.看到这个我就感觉不对了.脑海 ...
- 【安卓中的缓存策略系列】安卓缓存之内存缓存LruCache
缓存策略在移动端设备上是非常重要的,尤其是在图片加载这个场景下,因为图片相对而言比较大会花费用户较多的流量,因此可用缓存方式来解决,即当程序第一次从网络上获取图片的时候,就将其缓存到存储设备上,这样在 ...
- android WeakReference(弱引用 防止内存泄漏)与SoftReference(软引用 实现缓存机制(cache))
在Android开发中,基本上很少有用到软引用或弱引用,这两个东东若用的很好,对自己开发的代码质量的提高有很大的帮助.若用的不好,会坑了自己.所以,在还没有真正的去了解它们之前,还是慎用比较好. 下面 ...
- .NET Core应用中使用分布式缓存及内存缓存
.NET Core针对缓存提供了很好的支持 ,我们不仅可以选择将数据缓存在应用进程自身的内存中,还可以采用分布式的形式将缓存数据存储在一个“中心数据库”中.对于分布式缓存,.NET Core提供了针对 ...
- Java的四种引用——强引用、软引用、弱引用、虚引用
目录 强引用 软引用 弱引用 虚引用 强引用 拥有强引用的对象永远不会被GC,可以根据引用的get方法获取到被引用对象 软引用 在内存充足的额时候,拥有软引用的对象不会被GC:即将内存溢出的时候,会对 ...
随机推荐
- 引擎设计跟踪(九.9) 文件包系统(Game Package System)
很早之前,闪现过写文件包系统的想法, 但是觉得还没有到时候. 由于目前工作上在做android ndk开发, 所以业余时间趁热做了android的移植, 因为android ndk提供的mountab ...
- Python3中的新特性(3)——代码迁移与2to3
1.将代码移植到Python2.6 建议任何要将代码移植到Python3的用户首先将代码移植到Python2.6.Python2.6不仅与Python2.5向后兼容,而且支持Python3中的部分新特 ...
- 三维云模拟Three.js
http://www.mrdoob.com/#/131/clouds http://www.webgl.com/2012/03/webgl-demo-clouds/ <!DOCTYPE html ...
- unity3d中dllimport方法的使用,以接入腾讯平台为例!!!
说到有关dllimport方法可能还有很多人比较陌生,其实我自己也说不太清楚,大概说说什么时候要用它. 事实上功能类似于调用android的第三包,我们想要使用苹果上特定的api或者第三方平台的一些东 ...
- .net 类型源码下载地址
原文:http://www.cnblogs.com/ProJKY/p/SSCLI.html 一般场景下,采用 Reflector可以反射出.NET 的部分实现出来,可以拿来参考,但和微软公开的SSCL ...
- swift学习网站
http://letsswift.com/category/swiftguide/http://www.imooc.com/course/list?is_easy=3&c=ioshttp:// ...
- HDU 1385 Minimum Transport Cost (Dijstra 最短路)
Minimum Transport Cost http://acm.hdu.edu.cn/showproblem.php?pid=1385 Problem Description These are ...
- Android的Testing和Instrumentation
Android提供了一系列强大的测试工具,它针对Android的环境,扩展了业内标准的JUnit测试框架.尽管你可以使用JUnit测试Android工程,但Android工具允许你为应用程序的各个方面 ...
- 使用 Struts 2 开发 RESTful 服务
REST 简介 REST 是英文 Representational State Transfer 的缩写,这个术语由 Roy Thomas Fielding 博士在他的论文<Architectu ...
- **关于PHP如何定义一个空对象(REST API如何处理空对象和空数组)
在写接口的过程当中,手机端有需求说不让返回json数组,要返回一个对象. 那么我们可以怎么做呢? 其实很简单,强制转换即可. 声明空对象: $empty_object=(object)array(); ...