new Handler().postDelayed(new Runnable(){
@Override
public void run() {
// do stuff
}}, 100);
これをアクティビティ (onCreate または onResume など) から呼び出すと、メモリ リークが発生する可能性がありますか? new Runnable()
は実際には静的インスタンスであるべきだと読みましたが、本当ですか?
new Handler().postDelayed(new Runnable(){
@Override
public void run() {
// do stuff
}}, 100);
これをアクティビティ (onCreate または onResume など) から呼び出すと、メモリ リークが発生する可能性がありますか? new Runnable()
は実際には静的インスタンスであるべきだと読みましたが、本当ですか?
はい。このコードにより、メモリ リークが発生する可能性があります。
に基づくこの匿名クラスRunnable
がキューにある限り (この例では 100 ミリ秒)、外部Activity
クラスへの参照を保持します。
もちろん、このようなメモリ リーク自体は問題ではありませんが、内部run
で実行されるコードによっては、たとえば が強制終了された後にダイアログを表示しようとすると、アプリケーションがクラッシュするなど、より大きな問題が発生する可能性がありますActivity
。このような状況では、適切な情報例外が表示されます。
IllegalArgumentException: onSaveInstanceState の後にこのアクションを実行できません
また
BadTokenException: ウィンドウを追加できません - ... アクティビティは実行中ですか?
はい、これは漏れです。ハンドラーの動作方法により、ハンドラーが非常に長期間存続し、参照するリソースがガベージ コレクションされるのを防ぐことができます。ここに良い説明があります:http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html
ランナブルがオブジェクトの存続期間を超える可能性がある場合は、代わりにこちらの回答のアプローチを試してください: https://stackoverflow.com/a/27825703/579234
あなたがしていることは、非静的ハンドラー クラスに関する既存の Lint 警告をトリガーする通常のケースの上に別のレベルのオブジェクトを追加することで、Lint 警告がトリガーされます: Android lint のチェック:
ハンドラーリーク ----------- 概要: Handler クラスが への参照を保持しないようにします。 外側のクラス 優先度: 4 / 10 重大度: 警告 カテゴリ: パフォーマンス Android では、Handler クラスを静的にする必要があります。そうしないと、リークが発生する可能性があります。メッセージ アプリケーション スレッドの MessageQueue にエンキューされたものも、そのターゲットを保持します ハンドラ。ハンドラーが内部クラスの場合、その外部クラスはそのまま保持されます。 良い。外部クラスのリークを避けるために、Handler を static ネストされたものとして宣言します。 外部クラスへの WeakReference を持つクラス。
匿名クラスの使用は、http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.9.5に記載されているものと同じです:
匿名クラスは常に内部クラスです (§8.1.3)。決して静的ではありません (§8.1.1、§8.5.1)。
したがって、明示的に説明すると、ランナブルは「this」への参照を保持し、ハンドラーはランナブルへの参照を保持するため、ハンドラーが停止するまで「this」はガベージコレクションされません。