Androidでのメモリリーク回避
Android Developers BlogよりAvoiding memory leaksを読んで、個人的備忘録(なので、正確さは無保証です)。
# 追記:Android Zaurusさんのところに全訳がありました
不要な参照をしていると、期待通りにGCでメモリが解放されない(ここではこれをメモリリークと呼んでいる)わけだけど、Androidでは注意すべきところがある。
AndroidではいろいろなオブジェクトがContextという引数を取る。通常は現在のActivityを渡すのだが、これによりActivityが予想外に解放されなくなることがある。Activityは割と頻繁に生成/廃棄されるので(例えば縦横切り替えとか)これは問題だ。
例えば、Drawableはロード時間かかるのでアプリケーションでキャッシュしておきたくなる。ところが、DrawableはonCallbackのためにViewを参照しており、そのViewはContextとしてActivityを参照している。したがって、Drawableが生きているあいだはActivityが解放されなくなる。Homeではこれを回避するために、icon.setCallback(null)としていたりする。
こんなことにならないためには、Contextをそのスコープ外で参照しないようにする、また、アプリケーションで共通に利用するオブジェクトにはContext.getApplicationContext()やActivity.getApplication()を使って、ApplicationをContextとして渡してあげればよい。
覚えておくべきこと
- ActivityをContextとして長期間(Activityのライフサイクルを超えて)保持してはいけない
- 長期間保持するようなときにはApplicationをContextに使おう
- Activityのライフサイクルを制御できないときは、Activity内では非静的な内部クラスを避ける。静的な内部クラスを使って、そのActivityへの弱い参照を使うとよい(弱い参照だけだとGCの対象になるため)
- GCがあるからといって、メモリーリークが起こらないわけではない