【问题标题】:Android - dismissDialog does not dismiss the dialogAndroid-dismissDialog 不会关闭对话框
【发布时间】:2010-10-27 20:20:08
【问题描述】:

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

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

有什么理由会这样吗?

编辑

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

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 我做的,但为什么是第二次?)并且每次我改变方向时都会发生这种情况。

知道为什么会这样吗?

再次感谢

【问题讨论】:

  • 有人可以帮我解决这个问题吗?我看过很多关于这个问题的帖子和博客,但似乎没有一个有效的解决方案。

标签: android


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 我确实在 onCreate() 中看到了与 showDialog() 相同的问题 - 尽管这似乎只发生在通过调试器启动应用程序时。将 showDialog() 移动到 onPostCreate() 为我完成了这项工作 - 谢谢!
    • 很好的解决方案,只需使用 OnPostCreate 启动对话框 ... @Override public void onPostCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);启动应用程序(); }
    • 这是一个记录在案的 Android 错误:code.google.com/p/android/issues/detail?id=24646
    【解决方案3】:

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

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

    我一直在向自己证明我正在对正确的活动进行解雇并检查调用的次数等,但这是由幕后的一些诡计造成的。

    【讨论】:

      【解决方案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

      【讨论】:

        【解决方案5】:

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

        解决方案是调用 removeDialog 而不是 dissmissDialog()。 上面的哈里已经推荐了这一点,谢谢。

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

        13858


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

        【讨论】:

          【解决方案6】:

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

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

          考虑以下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 的实例dialog 实例变量引用了一个与屏幕上当前活动的实例不同的 Test 实例。

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

          private static Dialog dialog;

          【讨论】:

          • 谢谢约瑟夫。但正如你所说,修复实际上是一个黑客!我正在考虑改用服务。直到服务运行时,我才会显示对话框。这是解决这个问题的正确方法吗?
          • 这真的取决于应用程序。但你是对的,(非常)长时间运行的任务绝对应该放入服务中。
          【解决方案7】:

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

          我从我的 Handler 的 handleMessage(myMessage) 方法中调用 showDialog(MyDialogID) AND dismissDialog(MyDialogId)。

          在此之前,我在 onCreate() 方法中调用了 showDialog,并尝试在句柄消息中关闭对话框。为什么这解决了问题,我不知道。

          【讨论】:

            【解决方案8】:

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

            【讨论】:

              猜你喜欢
              • 2022-11-03
              • 1970-01-01
              • 2012-09-20
              • 1970-01-01
              • 2014-10-21
              • 2013-07-05
              • 2011-11-28
              • 1970-01-01
              相关资源
              最近更新 更多