Android - dismissDialog не закрывает диалог - PullRequest
22 голосов
/ 21 мая 2009

Я использую 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 ]

8 голосов
/ 06 декабря 2010

Лучшее решение для меня, похоже, использовать removeDialog (id) вместо dismissDialog (); Меньше повторного использования, но безопаснее (ничего не выбрасывает) и никаких проблем при смене ориентации.

6 голосов
/ 31 июля 2010

Я столкнулся с этим при отображении диалогового окна в переопределении onCreate для Activity. Попробуйте вместо этого переместить код, который приводит к отображению диалога, в переопределение onPostCreate. Кажется, это работает для меня.

5 голосов
/ 25 марта 2011

Я потратил целый день на такую ​​проблему, когда диалоги не закрывались при вызове dismissDialog. Это произошло после моего первого поворота экрана и после этого не сработало. Я использовал внешний AsyncTask, которому явно передана ссылка на состояние.

В конце концов решение было действительно простым .... removeDialog(int) вместо dismissDialog(int).

Я потратил то, что казалось вечным доказательством для себя, что я выполнял увольнение по правильной активности и проверял, сколько раз вещи вызывались и т. Д., Но это было вызвано некоторыми из jiggerypokery за кулисами.

4 голосов
/ 25 сентября 2009

Я недавно тоже столкнулся с этой проблемой. У меня есть приложение со многими действиями, все из которых нуждаются в доступе к глобальным объектам (соединения БД, списки данных и т. Д.), Поэтому я переопределил класс 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

3 голосов
/ 09 января 2011

После нажатия кнопки «Домой» и перехода к приложению morelocal (изменить язык устройства), когда я вернулся в свое приложение, новые диалоговые окна не могли быть закрыты с помощью dismissDialog (я запустил диалог из действия onCreate).

Решением было вызвать removeDialog вместо dismissDialog (). Это было рекомендовано Харри выше, многие спасибо.

Я создал отчет об ошибках Android:

13858


Решение - создать диалог, используя OnPostCreate вместо OnCreate. Я добавил эту информацию в отчет об ошибке и рекомендовал улучшить документацию диалога .

0 голосов
/ 10 августа 2016
 private AlertDialog alert11 = null;
 public void gpsDialog(){
    if (alert11 == null || !alert11.isShowing()) {
        AlertDialog.Builder builder1 = new AlertDialog.Builder(MainActivity.this);
        builder1.setMessage("GPS not On");
        builder1.setCancelable(true);

        builder1.setPositiveButton("Enable GPS",
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {

                    Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                    MainActivity.this.startActivity(intent);
                    dialog.dismiss();
                }
            });

        builder1.setNegativeButton("Cancel", 
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    dialog.dismiss();
                }
            });

    alert11 = builder1.create();

    alert11.show();

    }

}
0 голосов
/ 20 января 2012

Я экспериментировал с той же проблемой. Я создавал AlertDialog и ProgressDialog внутри обратного вызова onCreateDialog() и показывал их из onCreate(). Создание этих диалоговых окон непосредственно в onCreate (без использования onCreateDialog()) и отклонение их в onPause() работало для меня! На основании https://stackoverflow.com/a/5693467/955619

0 голосов
/ 22 июля 2010

После поиска по всем видам форумов я просто сделал следующее:

Я вызываю showDialog (MyDialogID) И dismissDialog (MyDialogId) из метода handleMessage (myMessage) из моего обработчика.

Перед этим я вызвал showDialog в моем методе onCreate () и попытался закрыть диалоговое окно в дескрипторе Message. Почему это решило проблему, я не могу сказать.

0 голосов
/ 23 мая 2009

Помните, что каждый раз, когда вы меняете ориентацию, создается новый экземпляр вашего Activity (и, следовательно, вашего Dialog через onCreateDialog). В этом можно убедиться, добавив оператор log в любой конструктор.

Хотя трудно сказать, не взглянув на ваш код, я предполагаю, что вы звоните dismissDialog на старшем экземпляре вашего Activity.

Рассмотрим следующий Activity, который просто показывает пустой Dialog при нажатии кнопки и запускает TimerTask, чтобы отклонить ее через 10 секунд:

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 никогда не отклоняется. Почему? Потому что в то время, когда TimerTask равен run, был создан совершенно другой набор Test и Dialog экземпляров (во время изменения ориентации) и TimerTask 's dialog переменная экземпляра ссылается на экземпляр Test, который отличается от того, который в данный момент активен на экране.

Очевидно, что есть несколько способов решения этой проблемы (в основном в зависимости от вашего приложения), одним быстрым (грязным?) Способом исправить вышеприведенный код было бы просто сделать поле dialog static:

private static Dialog dialog;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...