2

我正在开发一个需要加载位图的应用程序。并使用SoftReference缓存。我将每个软引用与 a 相关联,ReferenceQueue并使用哈希映射来访问SoftReference. 如下图所示:

public static class MemCache {

    final private ReferenceQueue<Bitmap> queue = new ReferenceQueue<Bitmap>();
    private Map<String, SoftReference<Bitmap>> hash = null;

    public MemCache() {
        hash = Collections.synchronizedMap(
            new LinkedHashMap<String, SoftReference<Bitmap>>()
        );
    }

    public synchronized Bitmap put(String key, Bitmap value) {
        clean();
        SoftReference<Bitmap> ref = new SoftReference<Bitmap>(value, queue);
        SoftReference<Bitmap> res = hash.put(key, ref);
        if (res == null) return null;
        return res.get();
    }

    public synchronized Bitmap get(Object key) {
        clean();
        SoftReference<Bitmap> ref = hash.get(key);
        if (ref == null) return null;
        Bitmap val = ref.get();
        if (val != null) return val;
        hash.remove(key);
        return null;
    }
}

然后,当我写clean()这样的:

    private synchronized void clean() {
        Reference<? extends Bitmap> sv;
        while ((sv = queue.poll()) != null)
            hash.remove(sv);
        Queue<String> toRemove = new LinkedList<String>();
        for(Entry<String, SoftReference<Bitmap>> e : hash.entrySet()){
            if(e.getValue()==null) continue;
            if(e.getValue().get()==null) 
                toRemove.add(e.getKey());
        }
        String s;
        while((s = toRemove.poll())!= null)
            hash.remove(s);
        Log.e("ImageCacheManager", "MemCache Size/2:" + new String(new char[hash.size() / 2]).replace("\0", "="));
    }

它检查哈希表中的所有 SoftReferences 是否不为空。内存缓存看起来不错,但如果我只写:

    private synchronized void clean() {
        Reference<? extends Bitmap> sv;
        while ((sv = queue.poll()) != null)
            hash.remove(sv);
        Log.e("ImageCacheManager", "MemCache Size/2:" + new String(new char[hash.size() / 2]).replace("\0", "="));
    }

只去掉被放入ReferenceQueue的元素,Log然后打印的越来越多=,虽然有一些减少,但有增加的趋势

正如http://www.ibm.com/developerworks/library/j-refs/中提到的

的设置为空referentSoftReference但大部分SoftReference不在ReferenceQueue。只是在对象被标记为可终结但未最终确定的状态之间?标记为 finalizable 但未最终确定的 Bitmap 会被回收吗?

4

1 回答 1

5

我已经尝试过类似的问题。一段时间后,我意识到这是因为 android 管理位图的方式。如果我没有误解,他们使用“skia”,一种本机实现,用于位图。所以位图不是在 Java 堆中分配的,而是在本机堆中分配的,而且 Java 位图对象本身非常小,不适合 GC。因此他们提供了释放位图保留的本机内存的回收方法。

对不起我糟糕的英语。

于 2011-11-22T08:29:23.890 回答