2

以下の例のメモリリーク。

1.SpeedHelper.java:

public class SpeedHelper {

    interface Listener {
        void OnSelected(String entry);
    }
    static Listener sListener;

    static void setListener(Listener listener) {
        sListener = listener;
    }
    static Listener getListener() {
        return sListener;
    }
    static void clearListener() {
        sListener = null;
    }
}

2.CallSpeed.java

public class CallSpeed {

    protected void speed() {
        SpeedHelper.Listener litener = SpeedHelper.getListener();
        if (litener != null) {
            litener.OnSelected("mEntry");
        }
    }
}

3.MainActivity.java

public class MainActivity extends Activity {

    private CallSpeed callspeed;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SpeedHelper.setListener(mCallSpeedListener);
        callspeed = new CallSpeed();
        callspeed.speed();
    }
    private SpeedHelper.Listener mCallSpeedListener = new SpeedHelper.Listener() {

        @Override
        public void OnSelected(String entry) {
            Toast.makeText(getApplicationContext(), entry, Toast.LENGTH_SHORT).show();
        }
    };
    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        SpeedHelper.clearListener();
    }
}

「sListener」のメモリリークを回避するにはどうすればよいですか?

4

2 に答える 2

1

static WeakReferences<Listener> sListenerクラスで変数定義に 使用しSpeedHelperて、getterメソッドとsetterメソッドを次のように変更することができます。

static void setListener(Listener listener) {
    sListener = new WeakReference(listener);
}
static Listener getListener() {
    return sListener.get();
}
于 2012-12-15T05:43:23.397 に答える
1

あなたの問題は、静的フィールドに関連する次の非静的で囲まれた匿名クラスにありますsListener

private SpeedHelper.Listener mCallSpeedListener = new SpeedHelper.Listener() {

        @Override
        public void OnSelected(String entry) {
            Toast.makeText(getApplicationContext(), entry, Toast.LENGTH_SHORT).show();
        }
    };

これは非静的な囲まれたクラスであるため、その外部クラスへの参照が含まれていますMainActivity。この非表示の参照は、オブジェクト(非表示の参照を含む)が命令とともに静的フィールドに格納されるMainActivityため、GCによるクラスの解放をブロックします。したがって、オブジェクトが収集されることはなく、その関数が呼び出されることもありません。また、すべてがメモリに残ります。GCの手の届かないところにあります。静的フィールドの使用は、メモリリークに対して広く開かれた扉であり、囲まれたクラス(匿名かどうかに関係なく)に隠された参照が存在すると、この問題が増幅されます。mCallSpeedListenersListenerSpeedHelper.setListener(mCallSpeedListener);MainActivityonDestroy

あなたの場合、静的フィールドを削除するかsListener、匿名クラスを通常のクラスに変更する必要があります。外部クラスへの非表示の参照がないもの、またはアクティビティが終了したときにアクティビティの別のコールバックでMainActivity直接呼び出すもの。clearListener

于 2012-12-15T07:19:54.977 に答える