iRSSの日記

はてなダイアリーiRSSの日記の続き

Androidでも起こるメモリリーク

Javaなので、メモリリークは起こらないと思ってたのですが、メモリーリークに相当するずい、実装はあり得ます。

画像をメモリキャッシュに入れようとして、いたのですが、その際に「やってはいけない」実装をやってました。
OutOfMemoryErrorが、画像の読み込み時に出るようになったのですが、

例えば、Drawableはロード時間かかるのでアプリケーションでキャッシュしておきたくなる。ところが、DrawableはonCallbackのためにViewを参照しており、そのViewはContextとしてActivityを参照している。したがって、Drawableが生きているあいだはActivityが解放されなくなる。

まさにこの事例どおりのことです。

こんなことにならないためには、Contextをそのスコープ外で参照しないようにする、また、アプリケーションで共通に利用するオブジェクトにはContext.getApplicationContext()やActivity.getApplication()を使って、ApplicationをContextとして渡してあげればよい。

覚えておくべきこと

ActivityをContextとして長期間(Activityのライフサイクルを超えて)保持してはいけない
長期間保持するようなときにはApplicationをContextに使おう
Activityのライフサイクルを制御できないときは、Activity内では非静的な内部クラスを避ける。静的な内部クラスを使って、そのActivityへの弱い参照を使うとよい(弱い参照だけだとGCの対象になるため)
GCがあるからといって、メモリーリークが起こらないわけではない

XXXActivity.thisをcontextとしてそのまま、使うのじゃなくて。

XXXActivity.this.getApplictionContextとすればOKのようです。


さらに、http://developer.android.com/intl/zh-CN/reference/java/lang/ref/SoftReference.htmlのSoftReferenceにしておけば、 OutOfMemoryErrorになりそうなときに、CGしてくれるようなので、消えてもいいキャッシュであれば、このSoftReferenceがよろしいかと思います(でも試してない)

サンプルソースなくて、すみません。わかりにくいね。