Ответ 1
Лучшее решение для меня, похоже, использует removeDialog (id) вместо rejectDialog(); Меньше повторного использования таким образом, но безопаснее (ничего не бросает) и никаких проблем при изменении ориентации.
Я использую showDialog()
и dismissDialog()
, чтобы показывать диалоги прогресса в моем приложении. Перемещено от создания диалога и вызова show()
на нем, чтобы использовать это, чтобы сохранить состояние при изменении ориентации.
Но когда я меняю ориентацию с портретом → пейзаж → портрет, dismissDialog()
больше не отклоняет диалог. Диалог остается там все время, и мне нужно нажать кнопку "Назад", чтобы он исчез.
Любая причина, по которой она будет вести себя таким образом?
Edit
Чтобы решить эту проблему, я попытался добавить 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, который я делаю, но почему второй раз?), и это происходит каждый раз, когда я меняю ориентацию и далее.
Любая идея, почему это происходит?
Еще раз спасибо
Лучшее решение для меня, похоже, использует removeDialog (id) вместо rejectDialog(); Меньше повторного использования таким образом, но безопаснее (ничего не бросает) и никаких проблем при изменении ориентации.
Я столкнулся с этим при показе диалога в переопределении onCreate Activity. Попробуйте переместить код, который заставляет диалоговое окно отображаться в переопределении onPostCreate. Кажется, это работает для меня.
Я потратил больше дня на такую проблему, когда диалоги не увольнялись при вызове функции dispDialog. Это произошло после моего первого поворота экрана и никогда не работало после этого. Я использовал внешнюю AsyncTask, которая была явно указана в ядре.
В итоге решение было действительно простым. removeDialog(int)
вместо dismissDialog(int)
.
Я потратил то, что чувствовал себя навсегда, доказывая, что я делаю увольнение на правильной деятельности и проверяю количество раз, когда что-то называлось и т.д., но это было вызвано некоторыми из jiggerypokery за кулисами.
Недавно я столкнулся с этой проблемой. У меня есть приложение со многими действиями, все из которых требуют доступа к глобальным объектам (соединения 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
После нажатия кнопки "домой" и перехода на приложение morelocal (сменить язык устройства), когда я вернусь в свое приложение, новые диалоговые окна не могут быть закрыты с помощью функции dispDialog (я запустил диалог из действия onCreate).
Решение заключалось в вызове removeDialog вместо dismissDialog(). Это было рекомендовано Харри выше, многие спасибо.
Я создал отчет об ошибке Android:
Решение состоит в том, чтобы создать диалог, используя OnPostCreate вместо OnCreate. Я добавил эту информацию в отчет об ошибке и рекомендовал улучшить диалоговую документацию .
Помните, что каждый раз, когда вы меняете ориентацию, создается новый экземпляр вашего 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
(во время изменения ориентации), а переменная экземпляра TimerTask
Dialog
ссылается на экземпляр Test
который отличается от того, который в данный момент активен на экране.
Очевидно, есть несколько способов решить эту проблему (в основном в зависимости от вашего приложения), один быстрый (грязный?) способ исправить вышеуказанный код состоит в том, чтобы просто сделать поле Dialog
static
:
private static Dialog dialog;
После поиска по всем форумам я просто сделал следующее:
Я вызываю showDialog (MyDialogID) и отклоняю диалог (MyDialogId) из метода handleMessage (myMessage) из моего обработчика.
До этого я вызвал showDialog в своем onCreate() - Method и попытался отклонить диалог в handle-Message. Почему это решило проблему, я не могу сказать.
Я экспериментировал с той же проблемой. Я создавал AlertDialog
и ProgressDialog
внутри обратного вызова onCreateDialog()
и показывал их из onCreate()
. Создание этих диалогов непосредственно в onCreate
(без использования onCreateDialog()
) и отключение их в onPause()
работало для меня!
На основе https://stackoverflow.com/a/5693467/955619
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();
}
}