2012-12-15 140 views
8

我正在构建一个android应用程序,其中每个实体都有一个代表其精灵的位图。但是,每个实体都可以被复制(例如,可能有3个实体asdf副本)。弱引用值的弱散列表?

一种方法是先加载所有的精灵,然后将正确的精灵放入实体的构造函数中。

但是,我想懒散地解码位图,以便实体的构造函数将解码位图。唯一的问题是重复的实体会使用两倍的内存来加载相同的位图(如果实体创建了n次,则重复n次)。

为了解决这个问题,我构建了一个SingularBitmapFactory,它将一个解码的Bitmap存储到一个散列中,并且如果再次询问相同的位图,只会返回之前散列的一个,而不是构建一个新散列。不过,问题在于工厂拥有所有位图的副本,因此不会收集垃圾。

将hashmap切换为弱引用值的最佳方式是什么?换句话说,我想要一个结构,如果任何其他对象持有对它的引用,值就不会GC'd,但只要没有其他对象引用它,那么它就可以GC'd。

回答

11

几乎你所说的 - 使Bitmap(地图的对象一侧)成为WeakReference而不是Bitmap。然后,您必须添加一个额外的检查,以查看引用在传递回实体之前是否仍然有效。这是一般想法的简要概述。

public class SingularBitmapFactory { 
    private HashMap <String, WeakReference<Bitmap>> cache = new HashMap<String, WeakReference<Bitmap>>(); 

    public Bitmap getBitmap(String key) { 
     Bitmap image = null; 
     WeakReference<Bitmap> ref = cache.get(key); 
     if(ref != null) { 
      image = ref.get(); 
     } 
     if(image == null) { 
      // Load image here ... 
      cache.put(key, new WeakReference<Bitmap>(image)); 
     } 
     return image; 
    } 
} 
+0

比你!这是非常简单和非常有效的情况下处理位图。只是使用绝对路径作为一个关键,它非常方便,并有助于摆脱泄漏 –

-3

最好的方法是使用WeakHashMap类,它为您完成所有工作,并且不需要对代码进行任何更改。这里有一个非常好的教程:http://weblogs.java.net/blog/2006/05/04/understanding-weak-references 它虽然比较古老,但仍然正常。 WeakHashMap存储对密钥的弱引用是很重要的。这意味着你不能只使用一个常量字符串值作为键,而是使用像Integer这样的东西,并将它作为弱引用存储在常量类中。

+1

嗯,从描述来看,WeakHashMap似乎对关键的引用不够强。 –

+0

它的确如此。谢谢。我已经编辑了答案。 – SIGKILL

+1

这不回答问题 – siledh

7

老问题,但我需要这样的今天,基于@ iagreen的答案,我全身的想法,也许它派上用场的人......

public static class WeakValueHashMap<K,V> { 
    private HashMap<K,WeakReference<V>> mDatabase=new HashMap<K, WeakReference<V>>(); 
    public V get(K key) { 
     WeakReference<V> weakRef=mDatabase.get(key); 
     if (weakRef==null) return null; 
     V result=weakRef.get(); 
     if (result==null) { 
      // edge case where the key exists but the object has been garbage collected 
      // we remove the key from the table, because tables are slower the more 
      // keys they have (@kisp's comment) 
      mDatabase.remove(key); 
     } 
     return result; 
    } 
    public void put(K key, V value) { 
     mDatabase.put(key, new WeakReference<V>(value)); 
    } 
} 

所以,你可以只是举例做

private WeakValueHashMap<String,Drawable> mTextDrawables=new WeakValueHashMap<String,Drawable>(); 

和图形内容将被存储与Weakreferences

的方法“中的containsValue”将是棘手的实施,你必须遍历和值访问所有的WeakRefs ...

+2

它似乎很不错:我认为你应该照顾过时的钥匙删除。一段时间后,很多键会使查找速度变慢。 (loadFactor会很高,会占用很多空间)。如果你不把钥匙取下。建议:在weakRef == null的情况下,在get方法中删除一个mDatabase。干杯 – kisp