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

您的问题在于以下与静态字段相关的非静态封闭匿名类sListener

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

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

因为这是一个非静态封闭类,它包含对其外部类的引用MainActivityMainActivity这个隐藏引用阻止了 GC释放类,因为mCallSpeedListener包含隐藏引用的对象sListener与指令一起存储在静态字段中SpeedHelper.setListener(mCallSpeedListener);。因此,MainActivity对象永远不会被收集,它的onDestroy函数永远不会被调用,一切都保留在内存中;GC 遥不可及。使用静态字段是内存泄漏的大门,封闭类中隐藏引用的存在(匿名或非匿名)放大了这个问题。

在您的情况下,您将不得不删除静态字段sListener或将匿名类更改为普通类;一个没有对其外部类的隐藏引用,或者在活动终止时MainActivity直接调用活动的另一个回调。clearListener

于 2012-12-15T07:19:54.977 回答
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 回答