为什么这个泄漏会轮流发生?

4
我发现了以下的内存泄漏示例。
package com.justinschultz.android;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;

public class LeakedDialogActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setIcon(android.R.drawable.ic_dialog_alert);
        builder.setMessage("This dialog leaks!").setTitle("Leaky Dialog").setCancelable(false).setPositiveButton("Ok", new DialogInterface.OnClickListener()
        {
            public void onClick(DialogInterface dialog, int which) {}
        });

        AlertDialog alert = builder.create();
        alert.show();
    }
}

我不明白为什么在旋转时会出现泄漏。我理解,当对话框仍然在屏幕上(包含对旧活动的引用)时,会创建一个新的活动。假设您关闭对话框并再次旋转。难道对最早活动的引用不应该消失,从而允许回收内存吗?


你确定有内存泄漏吗?你检查过堆增长了吗? - Federico Cristina
是的,根据LogCat的记录是这样的。我在这里找到了一个例子:http://publicstaticdroidmain.com/2012/01/avoiding-android-memory-leaks-part-1/。我有点明白为什么会出现内存泄漏,但我认为当用户关闭对话框后,垃圾回收器可以将其回收。 - jnb
1个回答

3
如果在碎片外使用AlertDialogs,应该通过onCreateDialog()/showDialog()实例化以避免泄漏。这种实现已经被弃用,应该被DialogFragment替代,但仍然适用。
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    showDialog(YOUR_DIALOG_ID);
}

@Override
protected Dialog onCreateDialog(int id) {
    switch(id) {
    case YOUR_DIALOG_ID:
        return new AlertDialog.Builder(LeakedDialogActivity.this)
        .setIcon(android.R.drawable.ic_dialog_alert)
        .setMessage("This dialog leaks!")
        .setTitle("Leaky Dialog")
        .setCancelable(false)
        .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {}
        })
        .create();
    }
    return super.onCreateDialog(id);
}

新增

如果不在onCreateDialog中创建对话框,则其实际上未连接到(或由)Activity拥有,因此也不属于它的生命周期。当Activity被销毁或重建时,对话框仍然保留对它的引用。

理论上,如果您使用setOwnerActivity()并在onPause()中解除对话框,则对话框应该不会泄漏(我相信是这样的)。

就一般泄漏而言,我不确定您是否需要太担心这个问题。对话框可以说是一种特殊情况。


1
嘿,保罗,谢谢你的回复!我发布的示例只是“教学性质的”。我希望找出泄漏的原因,以便避免易泄漏的做法。 - jnb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接