2009-05-21 2 views
22

Я использую showDialog() и dismissDialog(), чтобы показать диалоги прогресса в моем приложении. Перемещено от создания диалога и вызова show(), чтобы использовать это, чтобы сохранить состояние при изменении ориентации.Android - увольнениеDialog не отклоняет диалог

Но когда я меняю ориентацию с портретом -> пейзаж-> портрет, 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 [email protected] 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, который я делаю, но почему второй раз?), И это происходит каждый раз, когда я меняю ориентацию, а затем вперед.

Любая идея, почему это происходит?

Еще раз спасибо

+0

Может кто-то пожалуйста, помогите мне с этим вопросом? Я видел много сообщений и блогов об этой проблеме, но ни один из них не имеет решения, которое работает. – lostInTransit

ответ

0

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

Хотя трудно сказать, не взглянув на свой код, я предполагаю, что вы звоните 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 экземпляров был создан (при изменении ориентации) и dialog экземпляра переменных ссылках TimerTask «S A Test экземпляра, которая отличается от той, которая в данный момент активен на экран.

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

private static Dialog dialog;
+0

Спасибо, Josef. Но, как вы сказали, исправить на самом деле взломать! Я думаю об использовании Сервисов. Пока время службы работает, я показываю диалог. Это правильный путь? – lostInTransit

+0

Это действительно зависит от приложения. Но вы правы, (очень) длительные задачи обязательно должны быть включены в сервисы. –

4

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

.... случайные вещи здесь ....

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

0

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

Я называю ShowDialog (MyDialogID) И dismissDialog (MyDialogId) из-за handleMessage (MyMessage) Метод от моего обработчика.

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

6

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

+0

Я видел ту же проблему с showDialog() в onCreate() - хотя это, похоже, произошло только при запуске приложения через отладчик. Перемещение showDialog() в onPostCreate() выполнило задание для mee - спасибо! – sstn

+0

Отличное решение, просто используйте OnPostCreate для запуска диалога ... @Override public void onPostCreate (Bundle savedInstanceState) { super.onCreate (savedInstanceState); launch_app(); } –

+0

Это зарегистрированная ошибка Android: http://code.google.com/p/android/issues/detail?id=24646 –

7

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

3

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

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

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

13858


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

5

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

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

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

0

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

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

    } 

} 
Смежные вопросы