9

各エンティティにスプライトを表すビットマップがある Android アプリを構築しています。ただし、各エンティティは複製できます (たとえば、エンティティ asdf の 3 つのコピーがある場合があります)。

1 つの方法は、事前にすべてのスプライトをロードしてから、エンティティのコンストラクターに正しいスプライトを配置することです。

ただし、エンティティのコンストラクターがビットマップをデコードするように、ビットマップを遅延してデコードしたいと考えています。これに関する唯一の問題は、複製されたエンティティが同じビットマップを 2 回ロードし、2 倍のメモリを使用することです (エンティティが n 回作成された場合は n 回)。

これを修正するために、デコードされたビットマップをハッシュに格納する SingularBitmapFactory を構築しました。同じビットマップが再度要求された場合、新しいビットマップを構築する代わりに、以前にハッシュされたものを返すだけです。ただし、これの問題は、ファクトリがすべてのビットマップのコピーを保持しているため、ガベージ コレクションが行われないことです。

ハッシュマップを弱参照値を持つものに切り替える最良の方法は何ですか? 言い換えれば、他のオブジェクトがそれへの参照を保持している場合、値が GC されない構造が必要ですが、他のオブジェクトがそれを参照しない限り、GC されることができます。

4

3 に答える 3

12

あなたが言ったことのほとんど - Bitmap (マップのオブジェクト側) を Bitmap ではなく WeakReference にします。次に、追加のチェックを追加して、エンティティに戻す前に参照がまだ有効かどうかを確認する必要があります。ここでは、一般的なアイデアの簡単なスケッチを示します。

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;   
    }
}
于 2012-12-15T04:58:45.397 に答える
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>();

Drawables は に格納されWeakreferencesます。

メソッド「containsValue」は実装が難しく、すべての WeakRefs を反復して逆参照する必要があります ...

于 2014-09-02T23:48:34.393 に答える
-3

最善の方法は、すべての作業を自動的に行い、コードを変更する必要がない WeakHashMap クラスを使用することです。ここに非常に優れたチュートリアルがあります: http://weblogs.java.net/blog/2006/05/04/understanding-weak-references かなり古いですが、それでも問題ありません。WeakHashMap がキーへの弱参照を格納することが重要です。つまり、定数文字列値をキーとして使用するだけでなく、代わりに Integer のようなものを使用して、定数クラスに弱参照として格納できます。

于 2012-12-15T05:00:12.230 に答える