Androidでのメモリリーク回避

androidAndroid 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があるからといって、メモリーリークが起こらないわけではない