Boring Days as tech

金に生きるは下品にすぎる、 恋に生きるは切なすぎ、 出世に生きるはくたびれる。 とかくこの世は一天地六。 命ぎりぎり勝負をかける。 仕事はよろず引き受けましょう。 大小遠近男女は問わず、委細面談、仕事屋稼業。

WeakHashMap なるものがあるのね

SoftReferenceといふもの

久々にAndroid記事を書いてみるw
画像のメモリーに対する圧迫はAndroidアプリ開発のよくつっかかるポイントだと思うけれど、
そこで活躍するのは往往にしてSoftReferenceっつうクラスだと思う。
メモリーリークしそうになるとGC側が優先してSoftReferenceが持つオブジェクトを開放して、
メモリーの節約をさせるという形。
なのでたとえば、画像を相当数リスト表示する場合、オンメモリーにある画像を参照する場合、
このSoftReferenceを介することで、画面上に表示されない画像はGC側が優先的に破棄し、
相当数の画像リスト表示にも耐えられる実装となる。
結果メモリー管理も楽になれるという形。

//実装
SoftReference ref = new SoftReference<Bitmap>(bitmap);
//取得
Bitmap image = ref.get();
//解放
ref.clear();

http://developer.android.com/reference/java/lang/ref/SoftReference.html

SoftReferenceでの問題点

じゃあ、それで解決じゃんって話なんだけども、
これはSoftRefenrenceインスタンスの内部に持つObjectが解放される仕組みであって、
SoftReferenceインスタンス自体は解放されない。
なので、上記の画像のリスト表示なども、画面上に表示される画像オブジェクトは破棄されるのだが、
その画像を持っていたSoftReferenceインスタンスはメモリー上に残ったままなのである。
実際、残ってしまう空のSoftReferenceはメモリ圧迫には殆ど影響を及ぼさない量なのだけれど、
たとえば画像リスト表示を1000件以上だとかする場合、
1000個の空のSoftReferenceインスタンスがメモリー上に残ってしまう可能性がある。
こうなってくるとちょっと無視できなくなる。
そこでSoftReferenceインスタンスのリストが増えるたびに空のSoftReferenceインスタンスがないかチェックして、
あればそれを削除する、といった自前の実装が必要になってしまう。
しかしこれはメンドイ。

HashMap<string, SoftReference<Bitmap>> cache = new HashMap<string, SoftReference<Bitmap>>();

//空のインスタンスならリストから削除する
private void cleanCache(){
	for(string key : cache.keySet())
	{
		if(cache.get(key).get()==null){cache.remove(key);}
	}
}

WeakHashMap

そこでWeakHashMapの出番!
これはWeakReferenceというクラスに基づいて作られている拡張HashMapみたいなもの。
メモリーに対して一定の負荷がかかった時に内部で参照されてないオブジェクトがあった場合、
それをアイテムごと破棄してくれるというちょっと便利なモノ。
GCの判断で破棄されるのではなく、一定の負荷係数に応じて呼び出されるっぽい動き。
なので、空のインスタンスがメモリーに残ることはなく、
キャッシュの際などに大量のリスト状データが必要な場合はWeakHashMapの方が実装上楽に管理することが出来るでしょう。

//宣言するだけで後の処理は全部WeakHashMapにお任せ!
WeakHashMap<string, Bitmap> cache = new WeakHashMap<string, Bitmap>();

http://developer.android.com/reference/java/util/WeakHashMap.html



…というわけで、
WeakHashMapはふつーに昔からある代物だそうです。。。
でもSoftReferenceを使ったWeakHashMapなんてものはないみたい。

知らなかったー。