2009-05-21 8 views
22

Estoy usando showDialog() y dismissDialog() para mostrar los cuadros de diálogo de progreso en mi aplicación. Se movió desde la creación del cuadro de diálogo y llamando al show() para usarlo para guardar el estado al cambiar la orientación.Android - descartar el diálogo no descarta el diálogo

Pero cuando cambio la orientación de vertical-> horizontal-> vertical, el dismissDialog() ya no se cierra el cuadro de diálogo. El diálogo permanece ahí todo el tiempo y necesito presionar el botón Atrás para que desaparezca.

¿Alguna razón por la que se comportaría de esa manera?

Editar

Para superar este problema, he intentado añadir un removeDialog() en onDestroy() para que el diálogo no ha sido creada/aparece dos veces y antes del cambio de orientación, se retira el diálogo. añadiendo intentado declaraciones de registro y ver lo que sucede

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 

Si vemos aquí, en un principio, cuando se visualiza la actividad, el onCreateDialog se llama una vez y en el cambio de la orientación, onSaveInstanceState y OnDestroy se llaman.

Pero después de eso, onCreateDialog se llama dos veces (una vez por una llamada a showDialog que hago, pero ¿por qué la segunda vez?) Y esto sucede cada vez que cambio la orientación de aquí en adelante.

¿Alguna idea de por qué sucede eso?

Gracias de nuevo

+0

Puede alguien por favor me ayude con este problema? He visto muchas publicaciones y blogs sobre este tema, pero ninguno parece tener una solución que funcione. – lostInTransit

Respuesta

0

Por favor, tenga en cuenta que cada vez que cambie la orientación, una nueva instancia de su Activity (y por consiguiente de su Dialog través onCreateDialog) se crea. Puede verificar esto agregando una declaración de registro en cualquier constructor.

Aunque es difícil de decir sin echar un vistazo a su código, supongo que está llamando al dismissDialog en una instancia anterior de su Activity.

Considere lo siguiente Activity que simplemente muestra un vacío Dialog cuando se hace clic en un botón y comienza una TimerTask para descartarla después de 10 segundos:

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

Este código tiene un problema similar al que describes : Si - durante los 10 segundos - se cambia la orientación, el Dialog nunca se descarta. ¿Por qué? Debido a que en el momento de la TimerTask es run, un conjunto totalmente diferente de Test y Dialog casos ha sido creado (durante el cambio de orientación) y dialog instancia referencias a variables la TimerTask 's una instancia Test que es diferente de la que está actualmente activo en la pantalla.

Es obvio que hay varias maneras de hacer frente a este problema (sobre todo en función de su aplicación), una rápida (sucio?) Manera de solucionar el código anterior sería simplemente hacer que el campo dialogstatic:

private static Dialog dialog;
+0

Gracias Josef. ¡Pero como dijiste que arreglar es en realidad un truco! Estoy pensando en usar Servicios en su lugar. Hasta el momento en que se está ejecutando el servicio, muestro el diálogo. ¿Es esa la forma correcta de hacerlo? – lostInTransit

+0

Realmente depende de la aplicación. Pero tienes razón, las tareas (muy) largas definitivamente deberían incluirse en los servicios. –

4

Recientemente me encontré con este problema también.Tengo una aplicación con muchas actividades que necesitan acceder a los objetos globales (conexiones de base de datos, listas de datos, etc.) y así anulé la clase de aplicación. Con ese fin, me di cuenta de que todo lo que necesitaba era una referencia a la última instancia del cuadro de diálogo de progreso en mi ejecutable que estaba usando para descartar el diálogo. Esto es lo que me ocurrió y que sobrevive con gracia reorientaciones de teléfono:

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

.... cosas al azar aquí ....

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

Mi hilo hace un mHandler.post (showProgressRunnable) cuando la tarea comienza y luego hace un mHandler.post (hideProgressRunnable) cuando la tarea termina. Como la referencia al último ProgressDialog ahora está almacenada en la clase Application, puedo cerrarla de manera confiable ya que no estoy manteniendo una referencia de objeto anterior.

Enlace para la posteridad: http://developer.android.com/reference/android/app/Application.html

0

Después de buscar en todo tipo de foros, yo sólo hice lo siguiente:

que llamo el showDialog (MyDialogID) Y dismissDialog (MyDialogId) fuera de la handleMessage (myMessage) Método de mi Handler.

Antes de eso llamé a showDialog en mi método onCreate() e intenté cerrar el diálogo en handle-Message. Por qué esto resolvió el problema, no puedo decirlo.

6

Me he encontrado con esto al mostrar un cuadro de diálogo en la anulación onCreate de la Actividad. Intente mover el código que hace que el diálogo se muestre en la anulación de OnPostCreate. Esto parece funcionar para mí.

+0

Vi el mismo problema con showDialog() en onCreate(), aunque parece que esto solo ocurrió al iniciar la aplicación a través del depurador. Mover showDialog() a onPostCreate() hizo el trabajo por mí, ¡gracias! – sstn

+0

Gran solución, solo use OnPostCreate para abrir el cuadro de diálogo ... @Override public void onPostCreate (Bundle savedInstanceState) { super.onCreate (savedInstanceState); launch_app(); } –

+0

Esto es un error documentado de Android: http://code.google.com/p/android/issues/detail?id=24646 –

7

La mejor solución para mí parece usar removeDialog (id) en lugar de dismissDialog(); Menos reutilización de esta manera, pero más seguro (no tira nada) y sin problemas al cambiar de orientación.

3

Después de presionar el botón de inicio y navegar a la aplicación más local (cambiar el idioma del dispositivo), cuando volví a mi aplicación, los nuevos cuadros de diálogo no se podían cerrar mediante dismissDialog (inicié el diálogo desde la actividad onCreate).

La solución fue llamar a removeDialog en lugar de dissmissDialog(). Esto ha sido recomendado por Harri arriba, muchos thx.

He creado un informe de errores Android:

13858


solución es crear su diálogo utilizando OnPostCreate en lugar de OnCreate. Agregué esa información al informe de errores y le recomendé que mejorara el dialog documentation.

5

Perdí más de un día en un problema como este con diálogos que no se descartan al llamar a dismissDialog. Ocurrió después de mi primera rotación de pantalla y nunca funcionó después. Yo había estado usando una AsyncTask externa que se aprobó hace referencia al estado explícitamente.

Al final, la solución fue realmente simple .... removeDialog(int) en lugar de dismissDialog(int).

Pasé lo que pareció probarme para siempre. Estaba descartando la actividad correcta y comprobando el número de veces que se llamaron las cosas, etc., pero fue causada por la jiggerypokery detrás de las escenas.

0

Estaba experimentando el mismo problema. Estaba creando un AlertDialog y un ProgressDialog dentro de la devolución de llamada onCreateDialog() y mostrándolos desde el onCreate(). Crear estos cuadros de diálogo directamente en onCreate (sin usar onCreateDialog()) y descartarlos en onPause() funcionó para mí! Basado en 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(); 

    } 

} 
Cuestiones relacionadas