图片加载<第四篇>:学会使用软引用解决OOM问题

学会使用软引用和弱引用可以进一步优化内存泄漏问题。

本文主要让大家了解什么叫强引用软引用弱引用虚引用以及怎么使用。

(1)强引用(StrongReference)
Object object = new Object();
String name= "zhangsan";

强引用在项目中很常见,程序猿已经习惯性的使用强引用了,以上两句简单代码就是所谓的强引用。

当强引用对象占用的内存超过最大可分配内存时,就是发生OOM。

(2)软引用(SoftReference)

软引用是用来描述一些有用但并不是必需的对象,在Java中用java.lang.ref.SoftReference类来表示。对于软引用关联着的对象,只有在内存不足的时候JVM才会回收该对象。因此,这一点可以很好地用来解决OOM的问题,并且这个特性很适合用来实现缓存:比如网页缓存、图片缓存等。

SoftReference<String> str1 = new SoftReference<>(new String("hello1"));
Log.d("aaa", "str:"+str1.get());

//可以将软引用存入引用队列
ReferenceQueue<String> referenceQueue = new ReferenceQueue<>();
SoftReference<String> str2 = new SoftReference<>(new String("hello2"), referenceQueue);
Log.d("aaa", "str:"+str2.get());
(3)弱引用(WeakReference)

弱引用也是用来描述非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。在java中,用java.lang.ref.WeakReference类来表示。

WeakReference<String> str = new WeakReference<>(new String("hello"));
Log.d("aaa", "str:"+str.get());
System.gc();
Log.d("aaa", "str:"+str.get());

结果为:

(4)虚引用(PhantomReference)

虚引用和前面的软引用、弱引用不同,它并不影响对象的生命周期。在java中用java.lang.ref.PhantomReference类表示。如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收。

要注意的是,虚引用必须和引用队列关联使用,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会把这个虚引用加入到与之 关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

ReferenceQueue<String> queue = new ReferenceQueue<>();
PhantomReference<String> str = new PhantomReference<>(new String("hello"), queue);
Log.d("aaa", "str:"+str.get());

结果是:

(5)如何使用软引用解决OOM问题

BitmapFactory.decodeFile()将图片转成bitmap,这句代码是非常消耗性能的,为了防止同一张图片频繁的转成bitmap,我们需要将bitmap存入缓存,代码如下:

private Map<String, Bitmap> bitmaps = new HashMap();

/**
 * 将Bitmap保存到缓存
 * @param path 文件路径
 * @param bitmap 文件的bitmap对象
 */
private void addBitmapToCache(String path, Bitmap bitmap){
    bitmaps.put(path, bitmap);
}

/**
 * 获取缓存中的bitmap
 * @param path
 * @return
 */
private Bitmap getBitmap(String path){
    Bitmap bitmap = bitmaps.get(path);
    return bitmap;
}

这个想法不错,但是bitmap是非常占用内存的,如果缓存容器中存放多个bitmap对象很有可能造成OOM问题,解决OOM问题需要引用软引用或者弱引用软引用只有在内存不足的时候JVM才会回收该对象,弱引用无论内存是否充足,JVM进行垃圾回收时,都会回收被关联的对象。这里采用软引用较为适合。

private Map<String, SoftReference<Bitmap>> bitmaps = new HashMap();

/**
 * 将Bitmap保存到缓存
 * @param path 文件路径
 * @param bitmap 文件的bitmap对象
 */
private void addBitmapToCache(String path, Bitmap bitmap){
    bitmaps.put(path, new SoftReference<Bitmap>(bitmap));
}

/**
 * 获取缓存中的bitmap
 * @param path
 * @return
 */
private Bitmap getBitmap(String path){

    //获取软引用
    SoftReference<Bitmap> softReference = bitmaps.get(path);

    if(softReference == null){
        return null;
    }

    Bitmap bitmap = softReference.get();
    return bitmap;
}

以上代码是一个不错的方案,当获取的bitmap为null时,就重新在本地解码图片。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章