Android - dismissDialog不会忽略该对话框

时间:2009-05-21 05:04:04

标签: android

我正在使用showDialog()dismissDialog()在我的应用中显示进度对话框。从创建对话框开始,并在其上调用show()以使用此对话框,以便在更改方向时保存状态。

但是当我从纵向 - >横向 - >纵向更改方向时,dismissDialog()不再解除对话框。对话框一直停留在那里,我需要按后退按钮才能消失。

为什么会这样做?

修改

要解决此问题,我尝试在removeDialog()中添加onDestroy(),以便不会创建/显示对话框两次,在更改方向之前,会删除该对话框。尝试添加日志语句并查看会发生什么

05-21 12:35:14.064: DEBUG/MyClass(193): *************callingShowDialog
05-21 12:35:14.064: DEBUG/MyClass(193): *************onCreareDialog

05-21 12:35:15.385: DEBUG/MyClass(193): *************onSaveInstanceState
05-21 12:35:15.415: DEBUG/MyClass(193): *************onDestroy

05-21 12:35:15.585: DEBUG/MyClass(193): *************callingShowDialog
05-21 12:35:15.585: DEBUG/MyClass(193): *************onCreareDialog
05-21 12:35:15.715: DEBUG/MyClass(193): *************onCreareDialog
05-21 12:35:17.214: DEBUG/MyClass(193): *************onSaveInstanceState
05-21 12:35:17.214: DEBUG/MyClass(193): *************onDestroy

05-21 12:35:17.275: ERROR/WindowManager(193): android.view.WindowLeaked: Activity com.android.MyClass has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@43362088 that was originally added here

05-21 12:35:17.395: DEBUG/MyClass(193): *************callingShowDialog
05-21 12:35:17.395: DEBUG/MyClass(193): *************onCreareDialog
05-21 12:35:17.475: DEBUG/MyClass(193): *************onCreareDialog

如果我们在这里看到,最初显示活动时,会调用onCreateDialog一次,在更改方向时,会调用onSaveInstanceState和onDestroy。

但在那之后,onCreateDialog被调用两次(一次是通过调用我做的showDialog,但为什么是第二次?)并且每当我改变方向时都会发生这种情况。

知道为什么会这样吗?

再次感谢

9 个答案:

答案 0 :(得分:8)

对我来说最好的解决方案似乎是使用removeDialog(id)而不是dismissDialog();以这种方式减少重复使用,但更安全(不抛出任何东西)并且在更改方向时没有问题。

答案 1 :(得分:6)

我在活动的onCreate覆盖中显示一个对话框时遇到了这种情况。尝试将导致对话框显示的代码移动到onPostCreate覆盖中。这似乎对我有用。

答案 2 :(得分:5)

我浪费了一天这样的问题,在调用dismissDialog时对话框没有被解雇。它发生在我的第一次屏幕旋转之后,之后从未工作过。我一直在使用外部AsyncTask,它被明确地传递给了状态。

最后解决方案非常简单.... removeDialog(int)而不是dismissDialog(int)

我曾经感受到永远向自己证明我正在对正确的活动进行解雇并检查事情被召唤的次数等,但这是由幕后的一些jiggerypokery造成的。

答案 3 :(得分:4)

我最近遇到了这个问题。我有一个应用程序,有许多活动都需要访问全局对象(数据库连接,数据列表等),所以我覆盖了Application类。为此,我意识到我需要的只是对我运行中的进度对话框的最新实例的引用,我用它来关闭对话框。这就是我想出来的,它优雅地保留了电话重定向:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.preferences);

    mHandler = new Handler();
    mApplication = (MyApplication)getApplication();

    mFileStorage = (CheckBoxPreference)getPreferenceScreen().findPreference("fileStorage");

    mProgressDialog = new ProgressDialog(this);

    mProgressDialog.setTitle("Location Update");
    mProgressDialog.setMessage("Moving databases to new storage location.");
    mProgressDialog.setIndeterminate(true);
    mProgressDialog.setCancelable(false);
    mProgressDialog.setCanceledOnTouchOutside(false);

    mApplication.setProgressDialog(mProgressDialog);
}

@Override
protected void onResume() {
    super.onResume();

    mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
    mPreferences.registerOnSharedPreferenceChangeListener(this);

    if (sUpdateThread != null && sUpdateThread.isAlive()) {
        mProgressDialog.show();
    }
}

@Override
protected void onPause() {
    super.onPause();

    mPreferences.unregisterOnSharedPreferenceChangeListener(this);

    if (sUpdateThread != null && sUpdateThread.isAlive()) {
        mProgressDialog.hide();
        mApplication.setProgressDialog(null);
    }
}

....这里随意的东西......

private Runnable showProgressRunnable = new Runnable() {
    public void run() {
        mProgressDialog.show();
    }
};

private Runnable hideProgressRunnable = new Runnable() {
    public void run() {
        if (mApplication.getProgressDialog() != null) {
            mApplication.getProgressDialog().dismiss();
        }
    }
};

我的线程在任务启动时执行mHandler.post(showProgressRunnable),然后在任务完成时执行mHandler.post(hideProgressRunnable)。由于对最新ProgressDialog的引用现在存储在Application类中,因此我可以可靠地将其关闭,因为我不再持有旧的对象引用。

后人的链接:http://developer.android.com/reference/android/app/Application.html

答案 4 :(得分:3)

按下主页按钮并导航到app morelocal(更改设备语言)后,当我回到我的应用程序时,无法通过dismissDialog关闭新对话框(我从activity onCreate启动了对话框)。

解决方案是调用removeDialog而不是dissmissDialog()。 哈里上面推荐过这个,很多次。

我创建了一个Android错误报告:

13858


解决方案是使用OnPostCreate而不是OnCreate创建对话框。我将该信息添加到错误报告中,并建议改进dialog documentation

答案 5 :(得分:0)

#!/bin/bash
n=2
chr=o
str=
for ((i = 0; i < n; i++)); do 
    str="$str$chr"
done
printf "f%s\n" "$str"

答案 6 :(得分:0)

请注意,每次更改方向时,都会创建Activity(以及Dialog通过onCreateDialog)的新实例。您可以通过在任一构造函数中添加日志语句来验证这一点。

虽然很难说不用看你的代码,但我猜你是在dismissDialog的旧实例上调用Activity

考虑以下Activity,只需在点击按钮时显示空Dialog,并在10秒后启动TimerTask将其关闭:

public class Test extends Activity {

    private Dialog dialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);     
        setContentView(R.layout.test);
        Button btn = (Button) findViewById(R.id.testButton);
        btn.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                new Timer().schedule(new TimerTask() {
                    @Override public void run() { dialog.dismiss(); }
                }, 10000);
                Test.this.showDialog(1);
            }
        });
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        if(id == 1) {
            if(dialog == null) { dialog = new Dialog(this); }
            return dialog;
        }
        return super.onCreateDialog(id);
    }
}

此代码存在类似于您所描述的问题:如果 - 在10秒内 - 方向已更改,则Dialog永远不会被解除。 为什么?因为当TimerTaskrun时,已经创建了一组完整的TestDialog个实例(在定位更改期间)并且TimerTask的{​​{1}}实例变量引用的dialog实例与屏幕上当前活动的实例不同。

显然有几种方法可以解决这个问题(主要取决于你的应用程序),修复上述代码的一种快速(脏?)方法就是简单地制作Test字段dialog

static

答案 7 :(得分:0)

在搜索各种论坛后,我只是做了以下事情:

我从处理程序中调用了handleDessog(MyDialogID)和dismissDialog(MyDialogId)的handleMessage(myMessage)方法。

在此之前,我在我的onCreate() - Method中调用了showDialog,并尝试在handle-Message中关闭对话框。为什么这解决了这个问题,我不能说。

答案 8 :(得分:0)

我正在尝试同样的问题。我在AlertDialog回调中创建了ProgressDialogonCreateDialog(),并在onCreate()中展示了它们。直接在onCreate中创建这些对话框(不使用onCreateDialog())并在onPause()中解雇它们对我有用! 基于https://stackoverflow.com/a/5693467/955619