利用Java Soft Reference技术实现Android图片管理器
2013-05-17 10:13
573 查看
利用Java Soft Reference技术实现Android图片管理器
转自: http://www.cnblogs.com/Airforce-1/archive/2011/09/15/2178170.html
最近做一个项目,需要用到图片管理器,对所有的图片进行全局存储和读取。
目标比较明确:在不抛出OOM异常的情况下,尽量加速图片的读取速度。众所周知,手机这种资源受限型设备,对内存的使用还是需要精打细算的。
本人接触Java时间不长,3个月多一点,对Java的内存管理机制理解的不透彻,所以刚开始走了一些弯路,最后才找到了Soft Reference这个东西。看来,以后必须要学习一下
Java的内存管理啦(此时不得不怀念C的自由和强大)。
言归正传,还是说说这个图片管理器。项目中图片分2种类型,一种是系统资源图片,本质上是编译成Android R的二进制文件;
另一种是用户自定义的图片,大多数以png、bitmap的格式存储在本地或者服务器端。
所以在管理器中设计了2张HashMap存放这两类图片。本来想把图片设计成Bitmap的,后来发现设计成Drawable更加方便。
下面展示一下代码:由于是公司内部的项目,所以代码不能全部贴出来。要保持最起码的职业道德嘛。
目前为止,这段代码工作正常,通过打出的日志,可以看见,VM在某些时候的确释放了一些已经缓存在HashMap中的图片,目的大概就是书上说的避免抛出OOM异常吧。但是内存的实际使用效率如何,所谓的Soft Reference到底如何平衡时间和空间的,没有直接的说明数据。我设计了一种实验方法,评估这段代码的效率,用一个XML脚本不停地随机读取图片资源,看看手机的实际反应情况。很不幸,貌似手机反应有点慢,现在郁闷中。另外对于存储在服务器端的图片资源,目前的代码没有考虑到这一点,或许要开一个子线程去网
络上下载图片,那是后话了,目前还有一些人在狂写服务端的代码呢。
根据使用中出现的问题,我会持续更新这段代码的,以期完美实现最初的目标:既省内存又省时间。
另外,希望某位大侠给我介绍一些Java内存管理机制的知识,或者一起探讨一下也行。
ReferenceQueue() Constructs a new reference-object queue.
Method:
Reference<? extends T> poll() -------Polls this queue to see if a reference object is available.
Reference<? extends T> remove() ---Removes the next reference object in this queue, blocking until one becomes available.
Reference<? extends T> remove(long timeout) Removes the next reference object in this queue, blocking until either one becomes available or the given timeout period expire
转自: http://www.cnblogs.com/Airforce-1/archive/2011/09/15/2178170.html
最近做一个项目,需要用到图片管理器,对所有的图片进行全局存储和读取。
目标比较明确:在不抛出OOM异常的情况下,尽量加速图片的读取速度。众所周知,手机这种资源受限型设备,对内存的使用还是需要精打细算的。
本人接触Java时间不长,3个月多一点,对Java的内存管理机制理解的不透彻,所以刚开始走了一些弯路,最后才找到了Soft Reference这个东西。看来,以后必须要学习一下
Java的内存管理啦(此时不得不怀念C的自由和强大)。
言归正传,还是说说这个图片管理器。项目中图片分2种类型,一种是系统资源图片,本质上是编译成Android R的二进制文件;
另一种是用户自定义的图片,大多数以png、bitmap的格式存储在本地或者服务器端。
所以在管理器中设计了2张HashMap存放这两类图片。本来想把图片设计成Bitmap的,后来发现设计成Drawable更加方便。
下面展示一下代码:由于是公司内部的项目,所以代码不能全部贴出来。要保持最起码的职业道德嘛。
public class ImageManager { private static ImageManager gInstance_; private static Resources resourcesMan = R.getResources(); private HashMap<Integer, SystemImageRef> systemImageRefs; ///为什么要保存系统图片cache private ReferenceQueue<SystemImage> systemImageRefQueue; private HashMap<String, CustomImageRef> customImageRefs; private ReferenceQueue<CustomImage> customImageRefQueue; public static final String log_tag = "ImageManager "; private ImageManager() { systemImageRefs = new HashMap<Integer, SystemImageRef>(); systemImageRefQueue = new ReferenceQueue<SystemImage>(); customImageRefs = new HashMap<String, CustomImageRef>(); customImageRefQueue = new ReferenceQueue<CustomImage>(); } public static ImageManager getInstance() { if (gInstance_ == null) { gInstance_ = new ImageManager(); } return gInstance_; } public Drawable getSystemImage(int resourceID) { /* If it's already cached through soft reference, get it directly */ SystemImage sysImage = null; if (systemImageRefs.containsKey(resourceID)) { SystemImageRef ref = systemImageRefs.get(resourceID); sysImage = ref.get(); } if (null == sysImage) { sysImage = new SystemImage(resourceID); cacheSystemImage(sysImage); Log.i(log_tag, "Retrieve image from R, resourceID = " + resourceID); } return sysImage.getSystemImage(); } private void cleanSystemImageCache() { SystemImageRef ref = null; while ((ref = (SystemImageRef) systemImageRefQueue.poll()) != null) { systemImageRefs.remove(ref.resourceID); ///可以访问私有类对象的私有数据 } return; } private void cacheSystemImage(SystemImage em) ///创建一个system image的cache { cleanSystemImageCache(); SystemImageRef ref = new SystemImageRef(em, systemImageRefQueue); ///把引用加入到引用队列中. systemImageRefs.put(ref.resourceID, ref); return; } public Drawable getCustomImage(String imageURL) { if (null == imageURL || 0 == imageURL.length()) { return null; } /* If it's already cached through soft reference, get it directly */ CustomImage cusImage = null; if(customImageRefs.containsKey(imageURL)) { CustomImageRef ref = customImageRefs.get(imageURL); cusImage = ref.get(); } if (null == cusImage) { cusImage = new CustomImage(imageURL); cacheCustomImage(cusImage); Log.i(log_tag, "Retrieve image imageURL = " + imageURL); } return cusImage.getCustomImage(); } ////------------------------------------------ private void cacheCustomImage(CustomImage em) ////创建 { cleanCustomImageCache(); CustomImageRef ref = new CustomImageRef(em, customImageRefQueue); ///queue用来辅助管理,主要使用poll来管理 customImageRefs.put(ref.imageURL, ref); ///res是真正干活的 return; } private void cleanCustomImageCache() { CustomImageRef ref = null; while ((ref = (CustomImageRef) customImageRefQueue.poll()) != null) { customImageRefs.remove(ref.imageURL); } return; } public void clearCache() { cleanSystemImageCache(); cleanCustomImageCache(); systemImageRefs.clear(); customImageRefs.clear(); System.gc(); //System.runFinalization(); return; } private class SystemImage { private int resourceID; private Drawable systemDrawable; public SystemImage(int resourceID) { this.resourceID = resourceID; this.systemDrawable = resourcesMan.getDrawable(resourceID); } public int getResourceID() { return this.resourceID; } public Drawable getSystemImage() { return this.systemDrawable; } } private class CustomImage { private String imageURL; private Drawable customDrawable; public CustomImage(String imageURL) { this.imageURL = new String(imageURL); this.customDrawable = FileUtils.getDrawable(imageURL); } public String getImagePath() { return this.imageURL; } public Drawable getCustomImage() { return this.customDrawable; } } private class SystemImageRef extends SoftReference<SystemImage> { private int resourceID; public SystemImageRef(SystemImage em, ReferenceQueue<SystemImage> q) { super(em, q); resourceID = em.getResourceID(); } } private class CustomImageRef extends SoftReference<CustomImage> { private String imageURL; public CustomImageRef(CustomImage em, ReferenceQueue<CustomImage> q) { super(em, q); imageURL = em.getImagePath(); } } }
目前为止,这段代码工作正常,通过打出的日志,可以看见,VM在某些时候的确释放了一些已经缓存在HashMap中的图片,目的大概就是书上说的避免抛出OOM异常吧。但是内存的实际使用效率如何,所谓的Soft Reference到底如何平衡时间和空间的,没有直接的说明数据。我设计了一种实验方法,评估这段代码的效率,用一个XML脚本不停地随机读取图片资源,看看手机的实际反应情况。很不幸,貌似手机反应有点慢,现在郁闷中。另外对于存储在服务器端的图片资源,目前的代码没有考虑到这一点,或许要开一个子线程去网
络上下载图片,那是后话了,目前还有一些人在狂写服务端的代码呢。
根据使用中出现的问题,我会持续更新这段代码的,以期完美实现最初的目标:既省内存又省时间。
另外,希望某位大侠给我介绍一些Java内存管理机制的知识,或者一起探讨一下也行。
ReferenceQueue() Constructs a new reference-object queue.
Method:
Reference<? extends T> poll() -------Polls this queue to see if a reference object is available.
Reference<? extends T> remove() ---Removes the next reference object in this queue, blocking until one becomes available.
Reference<? extends T> remove(long timeout) Removes the next reference object in this queue, blocking until either one becomes available or the given timeout period expire
相关文章推荐
- Android性能优化之实现双缓存的图片异步加载工具(LruCache+SoftReference) - 拿来即用
- ANDROID_MARS学习笔记_S04_009_用java.lang.ref.SoftReference作缓存,android.os.Handler和new Thread异步加载略图片
- 利用SoftReference实现图片异步加载
- 利用SoftReference实现图片异步加载
- Android性能优化之实现双缓存的图片异步加载工具(LruCache+SoftReference) - 拿来即用
- android点击实现图片放大缩小 - java技术博客
- android使用lrucache与softReference对图片进行优化
- Android 利用WebViewJavascriptBridge 实现js和java的交互
- 【Android游戏开发十六】Android Gesture之【触摸屏手势识别】操作!利用触摸屏手势实现一个简单切换图片的功能!
- 利用WCF与Android实现图片上传并传参
- 利用Java代码实现图片的下载:
- 利用java实现简单图片的计数器
- 【转】【Java】利用反射技术,实现对类的私有方法、变量访问
- Android 利用Service实现下载网络图片至sdk卡
- Android使用RecyclerView和Picasso实现大规模浏览网络图片(附带缓存技术)
- (转)【Android游戏开发十六】Android Gesture之【触摸屏手势识别】操作!利用触摸屏手势实现一个简单切换图片的功能!
- Java项目开发心得(一):利用Java技术实现查询手机号码归属地
- android使用lrucache与softReference对图片进行优化
- android利用socket与java后台交互的设计与实现
- Android 利用TimerTask实现ImageView图片播放效果