`

[教程] 【转】Android 通过软引用实现图片缓存,防止内存溢出 [复制链接]

 
阅读更多


public class BitmapCache {
   
static private BitmapCache cache;
   
/** 用于Chche内容的存储 */
   
private Hashtable<Integer, MySoftRef> hashRefs;
   
/** 垃圾Reference的队列(所引用的对象已经被回收,则将该引用存入队列中) */
   
private ReferenceQueue<Bitmap> q;

    /**
     * 继承SoftReference,使得每一个实例都具有可识别的标识。
      
*/
   
private class MySoftRef extends SoftReference<Bitmap> {
        
private Integer _key = 0;

         public MySoftRef(Bitmap bmp, ReferenceQueue<Bitmap> q, int key) {
            
super (bmp, q);
            _key = key;
        }
    }

    private BitmapCache() {
        hashRefs =
new Hashtable<Integer, MySoftRef>();
        q =
new ReferenceQueue<Bitmap>();
    }

    /**
     * 取得缓存器实例
      
*/
   
public static BitmapCache getInstance() {
        
if (cache == null ) {
            cache =
new BitmapCache();
        }
        
return cache;
    }

    /**
     * 以软引用的方式对一个Bitmap对象的实例进行引用并保存该引用
      
*/
   
private void addCacheBitmap(Bitmap bmp, Integer key) {
        cleanCache();
// 清除垃圾引用
         MySoftRef ref = new MySoftRef(bmp, q, key);
        hashRefs.put(key, ref);
    }

    /**
     * 依据所指定的drawable下的图片资源ID号(可以根据自己的需要从网络或本地path下获取),重新获取相应Bitmap对象的实例
     
*/
   
public Bitmap getBitmap( int resId, Context context) {
        Bitmap bmp =
null ;
        
// 缓存中是否有该Bitmap实例的软引用,如果有,从软引用中取得。
          if (hashRefs.containsKey(resId)) {
            MySoftRef ref = (MySoftRef) hashRefs.get(resId);
            bmp = (Bitmap) ref.get();
        }
        
// 如果没有软引用,或者从软引用中得到的实例是null,重新构建一个实例,
         
// 并保存对这个新建实例的软引用
          if (bmp == null ) {
            
// 传说decodeStream直接调用JNI>>nativeDecodeAsset()来完成decode,
              
// 无需再使用java层的createBitmap,从而节省了java层的空间。
              bmp = BitmapFactory.decodeStream(context.getResources()
                    .openRawResource(resId));
            
this .addCacheBitmap(bmp, resId);
        }
        
return bmp;
    }

    private void cleanCache() {
        MySoftRef ref =
null ;
        
while ((ref = (MySoftRef) q.poll()) != null ) {
            hashRefs.remove(ref._key);
        }
    }

    /**
     * 清除Cache内的全部内容
     
*/
   
public void clearCache() {
        cleanCache();
        hashRefs.clear();
        System.gc();
        System.runFinalization();
    }
}


*****************************************************

*****************************************************
一般Java虚拟机要求支持verbosegc选项,输出详细的垃圾收集调试信息。dalvik虚拟机很安静的接受verbosegc选项,然后什么都不做。dalvik虚拟机使用自己的一套LOG机制来输出调试信息。

如果在Linux下运行adb logcat命令,可以看到如下的输出:

D/dalvikvm(  745): GC_CONCURRENT
freed 199K, 53% free 3023K/6343K,external 0K/0K, paused 2ms+2ms

其中D/dalvikvm表示由dalvikvm输出的调试信息,括号后的数字代表dalvikvm所在进程的pid。


GC_CONCURRENT表示触发垃圾收集的原因,有以下几种:






GC_MALLOC, 内存分配失败时触发


GC_CONCURRENT,当分配的对象大小超过384K时触发


GC_EXPLICIT,对垃圾收集的显式调用(System.gc)


GC_EXTERNAL_ALLOC,外部内存分配失败时触发


freed 199K表示本次垃圾收集释放了199K的内存,


53% free 3023K/6343K,其中6343K表示当前内存总量,3023K表示可用内存,53%表示可用内存占总内存的比例。


external 0K/0K,表示可用外部内存/外部内存总量

paused
2ms+2ms,第一个时间值表示markrootset的时间,第二个时间值表示第二次mark的时间。如果触发原因不是GC_CONCURRENT,这一行为单个时间值,表示垃圾收集的耗时时间。

分享到:
评论

相关推荐

    加载大图片的时候如何防止内存溢出

    防止内存溢出的关键是了解 Android 加载图片的机制,并掌握一些防止内存溢出的技巧,如使用 BitmapFactory.Options 对图片进行压缩,运用 Java 软引用进行图片缓存,及时回收图片所占的内存等。只有这样,我们才能在...

    Android防止内存溢出浅析.zip

    1. **Android内存管理机制** - **Dalvik/ART虚拟机**:Android系统使用Dalvik或ART虚拟机执行应用程序,它们都有自己的内存管理策略。 - **堆内存**:Java对象主要存储在堆中,Android为每个应用分配了一定量的堆...

    Android有效解决加载大图片时内存溢出的问题

    例如,可以使用软引用(SoftReference)来缓存图片,从而减少内存的消耗。 四、使用 Android 中的内存优化技术 在 Android 中,可以使用一些内存优化技术来减少内存的消耗。例如,可以使用 Android 中的 LruCache ...

    android 轻松避免内存溢出

    1. **Android内存机制**: - Android系统为每个应用程序分配了一定量的内存,不同版本的Android系统分配的内存大小不同。 - 当应用占用的内存超过分配的阈值时,就会触发垃圾回收(Garbage Collection, GC),回收...

    基于软引用实现的缓存,当内存不够使会自动释放缓存内容,以避免OOM

    基于软引用实现的缓存是一种优化策略,它能够帮助我们平衡性能和内存使用,防止因内存过度消耗而导致的OutOfMemoryError(OOM)。本篇文章将深入探讨软引用在缓存中的应用以及其工作原理。 软引用是Java中的一个...

    android 图片下载 有效解决内存溢出问题

    4. **使用软引用和弱引用**:通过使用软引用(SoftReference)和弱引用(WeakReference)来保存Bitmap对象,以便在内存不足时自动释放,降低内存泄漏风险。 5. **避免一次性加载过多图片**:在滚动列表(如ListView...

    android 显示大的gif图片 能解决内存溢出的问题

    在Android平台上,显示大型GIF图像可能会导致内存溢出(Memory Overflow)问题,因为GIF是一种动画格式,它包含多帧连续的图像,如果直接加载到内存中,会占用大量资源。为了解决这个问题,我们可以采用一些技术策略...

    android图片瀑布流优化版,防止内存溢出

    综上所述,这个优化版的Android图片瀑布流解决方案综合运用了多种技术手段,以防止内存溢出,提升应用的稳定性和性能。开发者在实现自己的瀑布流布局时,可以参考这些优化策略,为用户提供流畅且高效的图片浏览体验...

    android解决加载图片内存溢出

    在Android开发中,图片加载是常见且关键的操作,但如果不恰当处理,很容易导致内存溢出(Out of Memory,简称OOM)问题。内存溢出不仅会影响应用的性能,降低用户体验,严重时甚至会导致应用崩溃。本篇文章将深入...

    Android 图片下载以及内存处理防止OOM内存溢出 源码

    在Android开发中,图片的加载和内存管理是一个关键问题,特别是考虑到防止因内存溢出(Out Of Memory,简称OOM)而导致应用崩溃。本教程将详细探讨如何在Android中有效地进行图片下载和内存处理,以避免OOM的发生。 ...

    Android防止内存溢出浅析

    首先,我们需要理解Android内存管理的基本原理。Android应用程序基于Java语言,因此其内存机制与Java相似。Java的垃圾回收(GC)机制会自动回收不再使用的对象,但并不意味着开发者可以完全忽视内存管理。Android系统...

    android异步加载网络图片,双缓存内存加sd卡缓存 绝对不会出现内存溢出oom

    本文将深入探讨如何实现一个高效、安全的网络图片加载机制,结合双缓存策略,确保图片加载过程既快速又不会导致内存溢出(Out Of Memory, OOM)。 首先,我们要理解为什么需要异步加载。在Android中,如果在主线程...

    Android 内存溢出问题

    本篇文章将深入探讨Android内存管理的两个核心概念:堆(Heap)和栈(Stack),以及如何理解和解决Android内存溢出问题。 1. 堆与栈 堆和栈是Java虚拟机(JVM)中的两种主要内存区域,它们各自具有特定的用途和...

    基于Android防止内存溢出浅析

    使用LRU(Least Recently Used)算法的软引用或弱引用缓存,能在内存不足时自动清除不活跃的对象,防止内存溢出。 **生命周期管理** 理解并正确处理Android组件(如Activity、Service)的生命周期是防止内存溢出的...

    易语言防止文件内存溢出源码

    通过学习和理解这段代码,开发者可以更好地掌握在易语言中处理大文件和防止内存溢出的技巧,提高程序的稳定性和效率。 由于没有提供具体的源码内容,无法深入讨论细节,但以上概述了在易语言环境下防止文件内存溢出...

    易语言防止文件内存溢出

    总结来说,易语言防止文件内存溢出的关键在于分块读取和及时释放内存,通过“读入子程序”实现这一目标。在编程实践中,应结合错误处理、数据结构优化等策略,以确保程序的稳定性和效率。通过深入理解这些知识点并...

    防止内存溢出浅析

    本文将深入浅谈如何防止Android应用程序中的内存溢出。 首先,我们需要理解Android应用的内存管理机制。Android系统采用垃圾回收(Garbage Collection, GC)机制来自动释放不再使用的对象所占用的内存。当一个对象...

    ListView加载网络图片,防止内存溢出

    本篇文章将深入探讨如何在ListView中加载网络图片,并提供策略防止内存溢出。 首先,我们需要理解内存溢出的原因。当一个Android应用分配的内存超过系统允许的最大限制时,就会发生内存溢出。在ListView中加载网络...

    android图片缓存优化,内存缓存加sdcard缓存,性能很好,防止oom

    在Android应用开发中,图片加载和管理是性能优化的关键领域,因为不当的处理方式往往会导致内存溢出(OOM)问题,影响用户体验甚至导致应用崩溃。本文将深入探讨Android图片缓存的优化策略,包括内存缓存和SDCard...

Global site tag (gtag.js) - Google Analytics