6

次のようなアクティビティがあります。

class MyActivity extends Activity {
    Runnable refreshTimer = new Runnable() {
        public void run() {
            refresh();
        }
    };

    protected onCreate(...) {
        handler.postAtTime(refreshTimer, ...);
    }

    protected onDestroy() {
        handler.removeCallbacks(refreshTimer);
    }

    protected void refresh() { ... }
}

onDestroyが呼び出された後も、何らかの理由でMyActivity $ 0(更新Runnable)への参照を含むメッセージがアクティビティのMessageQueueにあります。MyActivity $ 0にはMyActivityへの暗黙の参照があるため、これによりMyActivityコンテキストのメモリリークが発生します。

Eclipseメモリアナライザーツールを使用したファントム、ソフト、ウィークなどの参照を除くandroid.app.Activityのmerge_shortest_pathsの結果: ここに画像の説明を入力してください

(上記のソースコードは、MATダンプに表示される実際のオブジェクト関係を簡略化したものです)

removeCallbacksを呼び出すと、実行可能なオブジェクトへの参照がキューから削除されるべきではありませんか?なぜコンテキストをリークしているのですか?

4

1 に答える 1

2

試してみること:

Androidのドキュメントによると:

OnDestroy : アクティビティが破棄される前に受け取る最後の呼び出し。これは、アクティビティが終了している (finish() が呼び出された) ため、またはシステムがスペースを節約するためにアクティビティのこのインスタンスを一時的に破棄しているために発生する可能性があります。これら 2 つのシナリオは、isFinishing() メソッドで区別できます。

アクティビティを終了するとき、キューに入れられたメッセージがまだたくさんあり、登録解除のコンテキストがキャンセル コールバックを呼び出していないようです。

onPauseでランナブルの登録を解除する必要があります。このコールバックは主に、アクティビティが編集している永続的な状態を保存し、「その場で編集」モデルをユーザーに提示し、十分なリソースがない場合に何も失われないようにするために使用されます。最初にこれを強制終了せずに新しいアクティビティを開始します。これは、次のアクティビティにできるだけ早く切り替えたり、カメラなどの排他的アクセスであるリソースを閉じたりするために、アニメーションを停止したり、CPU を大量に消費するその他のことを行うのにも適しています。

通常、Receiver または "Scheduled" Runnable は onResume に登録し、onPause で登録解除して、ライフサイクルのペアリングを改善します。

リフレッシュで何を行っているかを確認しないと、リフレッシュ メソッドで参照されるアクティビティ スコープのアクティビティ参照が原因で、リークが発生している可能性があると判断するのは困難です。

于 2013-07-27T02:01:50.957 に答える