Android-dismissDialog 不会关闭对话框

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/891451/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 02:29:27  来源:igfitidea点击:

Android - dismissDialog does not dismiss the dialog

android

提问by lostInTransit

I am using the showDialog()and dismissDialog()to show progress dialogs in my app. Moved from creating the dialog and calling show()on it to using this in order to save state when changing orientation.

我正在使用showDialog()dismissDialog()在我的应用程序中显示进度对话框。从创建对话框并调用show()它移动到使用它以在更改方向时保存状态。

But when I change the orientation from portrait->landscape->portrait, the dismissDialog()no longer dismisses the dialog. The dialog stay there all the time and I need to press the back button for it to disappear.

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

Any reason why it would behave that way?

有什么理由让它那样做吗?

Edit

编辑

To overcome this issue, I tried adding a removeDialog()in onDestroy()so that the dialog is not created/displayed twice and before orientation change, the dialog is removed. Tried adding log statements and see what happens

为了克服这个问题,我尝试添加一个removeDialog()inonDestroy()以便对话框不会被创建/显示两次,并且在方向改变之前,对话框被删除。尝试添加日志语句,看看会发生什么

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

If we see here, initially when the activity is displayed, the onCreateDialog is called once and on changing the orientation, onSaveInstanceState and onDestroy are called.

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

But after that, onCreateDialog is called twice (once by a call to showDialog which I make, but why the 2nd time?) and this happens every time I change the orientation hence forth.

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

Any idea why that happens?

知道为什么会这样吗?

Thanks again

再次感谢

回答by Harri

The best solution for me seems to use removeDialog(id) instead of dismissDialog(); Less re-usage this way, but safer (doesn't throw anything) and no problems when changing orientation.

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

回答by sakamoto

I've run into this when showing a dialog in the onCreate override of the Activity. Try moving the code that causes the dialog to be shown into the onPostCreate override instead. This seems to work for me.

在 Activity 的 onCreate 覆盖中显示对话框时,我遇到了这个问题。尝试将导致对话框显示的代码移到 onPostCreate 覆盖中。这似乎对我有用。

回答by Uniqe

I wasted over a day on a problem like this with dialogs not being dismissed when calling dismissDialog. It occurred after my first screen rotation and never worked afterwards. I had been using an external AsyncTask which was passed a referenced to the state explicitly.

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

In the end the solution was really simple.... removeDialog(int)instead of dismissDialog(int).

最后,解决方案真的很简单....removeDialog(int)而不是dismissDialog(int).

I had spent what felt like forever proving to myself I was doing the dismiss on the correct activity and checking the number of times things were called etc, but it was caused by some of the jiggerypokery behind the scenes.

我花了很多时间向自己证明我正在对正确的活动进行解雇并检查事物被调用的次数等,但这是由幕后的一些jiggerypokery造成的。

回答by MattC

I recently ran into this problem as well. I have an application with many activities all needing to access global objects (db connections, lists of data, etc) and so I overrode the Application class. To that end, I realized all I needed was a reference to the latest instance of the progress dialog in my runnable that I was using to dismiss the dialog. This is what I came up with and it gracefully survives phone reorientations:

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

@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);
    }
}

....random stuff here....

....这里是随机的东西....

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();
        }
    }
};

My thread does an mHandler.post(showProgressRunnable) when the task starts and then does an mHandler.post(hideProgressRunnable) when the task finishes. Since the reference to the latest ProgressDialog is now stored in the Application class, I can close it out reliably since I am no longer holding on to an old object reference.

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

Link for posterity: http://developer.android.com/reference/android/app/Application.html

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

回答by Michael Biermann

After pressing the home button and navigating to app morelocal (change device language), when I came back to my app, new dialog boxes could not be closed via dismissDialog (I launched the dialog from activity onCreate).

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

The solution was to call removeDialog instead of dissmissDialog(). This has been recommended by Harri above, many thx.

解决方案是调用 removeDialog 而不是 dissmissDialog()。这已经被哈里推荐了,很多谢谢。

I have created an Android bug report:

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

13858

13858



Solution is to create your dialog using OnPostCreate instead of OnCreate. I added that info to the bug report and recommended to improve the dialog documentation.

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

回答by Caumons

I was experimenting the same issue. I was creating an AlertDialogand a ProgressDialoginside the onCreateDialog()callback and showing them from the onCreate(). Creating these dialogs directly in onCreate(without using onCreateDialog()) and dismissing them in onPause()worked for me! Based on https://stackoverflow.com/a/5693467/955619

我正在试验同样的问题。我在回调中创建了一个AlertDialog和一个ProgressDialogonCreateDialog()并从onCreate(). 直接在onCreate(不使用onCreateDialog())中创建这些对话框并关闭它们onPause()对我有用!基于https://stackoverflow.com/a/5693467/955619

回答by Pascal Klein

After searching through all kinds of forums, i just did the following:

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

I call the showDialog(MyDialogID) AND dismissDialog(MyDialogId) out of the handleMessage(myMessage) Method from my Handler.

我从我的处理程序的 handleMessage(myMessage) 方法中调用 showDialog(MyDialogID) 和激怒Dialog(MyDialogId)。

Before that i called showDialog in my onCreate()-Method and tried to dismiss the dialog in handle-Message. Why this solved the problem, i cant tell.

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

回答by Josef Pfleger

Please be aware that every time you change the orientation, a new instance of your Activity(and consequently of your Dialogvia onCreateDialog) is created. You can verify this by adding a log statement in either constructor.

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

Although difficult to say without having a glance at your code, I'm guessing you're calling dismissDialogon an older instance of your Activity.

虽然不看你的代码很难说,但我猜你正在调用dismissDialog你的Activity.

Consider the following Activitythat simply shows an empty Dialogwhen a button is clicked and starts a TimerTaskto dismiss it after 10 seconds:

考虑以下内容ActivityDialog当单击按钮时仅显示一个空,并TimerTask在 10 秒后启动 a以关闭它:

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);
    }
}

This code has a problem similar to the one you're describing: If - during the 10 seconds - the orientation is changed, the Dialogis never dismissed. Why?Because at the time the TimerTaskis run, a whole different set of Testand Dialoginstances has been created (during orientation change) and the TimerTask's dialoginstance variable references a Testinstance that is different from the one that is currently active on the screen.

此代码有一个类似于您所描述的问题:如果 - 在 10 秒内 - 方向发生变化,Dialog则永远不会解除。为什么?因为当时TimerTaskis run,已经创建了一组完全不同的TestDialog实例(在方向更改期间),并且TimerTaskdialog实例变量引用了Test一个与当前屏幕上活动的实例不同的实例。

Obviously there are several ways to deal with this issue (mostly depending on your application), one quick (dirty?) way to fix the above code would be to simply make the dialogfield static:

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

private static Dialog dialog;