2009-05-21 19 views
22

Sto usando il showDialog() e dismissDialog() per mostrare le finestre di dialogo di avanzamento nella mia app. Spostato dalla creazione della finestra di dialogo e chiamando show() su di esso per utilizzare questo per salvare lo stato quando si cambia orientamento.Android - dismissDialog non chiude la finestra di dialogo

Ma quando cambio l'orientamento da verticale-> orizzontale-> verticale, lo dismissDialog() non chiude più la finestra di dialogo. La finestra di dialogo rimane lì tutto il tempo e ho bisogno di premere il pulsante Indietro per farla sparire.

Qualsiasi motivo per cui si comporterebbe in questo modo?

Modifica

Per superare questo problema, ho provato ad aggiungere un removeDialog() in onDestroy() in modo che la finestra di dialogo non viene creato/visualizzata due volte e prima di cambiare l'orientamento, la finestra di dialogo viene rimosso. aggiungendo provato dichiarazioni di registro e vedere cosa succede

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 

Se vediamo qui, inizialmente quando si visualizza l'attività, l'onCreateDialog viene chiamato una volta e su come cambiare l'orientamento, onSaveInstanceState e OnDestroy sono chiamati.

Ma dopo questo, onCreateDialog viene chiamato due volte (una volta da una chiamata a showDialog che faccio, ma perché la seconda volta?) E questo accade ogni volta che cambio l'orientamento, quindi avanti.

Qualche idea del motivo?

Grazie ancora

+0

Qualcuno può aiutarmi con questo problema? Ho visto molti post e blog su questo problema, ma nessuno sembra avere una soluzione che funzioni. – lostInTransit

risposta

0

Si prega di essere consapevoli del fatto che ogni volta che si cambia l'orientamento, una nuova istanza del vostro Activity (e di conseguenza del vostro Dialog tramite onCreateDialog) è stato creato. È possibile verificare ciò aggiungendo un'istruzione di registro in qualsiasi costruttore.

Anche se difficile da dire senza dare un'occhiata al codice, suppongo che tu stia chiamando dismissDialog in un'istanza precedente di Activity.

Si consideri il seguente Activity che mostra semplicemente un vuoto Dialog quando un pulsante viene premuto e inizia una TimerTask di respingerlo dopo 10 secondi:

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

Questo codice ha un problema simile a quello che stai descrivendo : Se - durante i 10 secondi - l'orientamento viene modificato, lo Dialog non viene mai chiuso. Perché? Poiché all'epoca il TimerTask è run, tutta una serie diversa di Test e Dialog casi è stato creato (durante il cambio di orientamento) e dialog istanza riferimenti variabili s' il TimerTask un'istanza Test che è diversa da quella che è attualmente attivo lo schermo.

Ovviamente ci sono diversi modi per affrontare questo problema (per lo più a seconda dell'applicazione in uso), una rapida (sporco?) Modo per risolvere il codice di cui sopra sarebbe quella di fare semplicemente il dialog campo static:

private static Dialog dialog;
+0

Grazie Josef. Ma come hai detto che la correzione è in realtà un hack! Sto pensando di usare invece i servizi. Fino al momento in cui il servizio è in esecuzione, mostro la finestra di dialogo. È la strada giusta da fare per questo? – lostInTransit

+0

Dipende davvero dall'applicazione. Ma hai ragione, (molto) le attività di lunga durata dovrebbero essere sicuramente inserite nei servizi. –

4

Recentemente mi sono imbattuto in questo problema.Ho un'applicazione con molte attività tutte che necessitano di accedere a oggetti globali (connessioni db, liste di dati, ecc.) E quindi ho scavalcato la classe Application. A tal fine, mi sono reso conto che tutto ciò di cui avevo bisogno era un riferimento all'ultima istanza della finestra di dialogo di avanzamento nella mia eseguibile che stavo usando per chiudere la finestra di dialogo. Questo è ciò che mi è venuta e sopravvive con grazia riorientamenti telefonici:

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

.... cose a caso qui ....

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

mio thread fa un mHandler.post (showProgressRunnable) quando l'attività inizia e quindi mHandler.post (hideProgressRunnable) al termine dell'attività. Poiché il riferimento all'ultima ProgressDialog è ora memorizzato nella classe Application, posso chiuderlo in modo affidabile poiché non sto più tenendo un riferimento a un vecchio oggetto.

link per i posteri: http://developer.android.com/reference/android/app/Application.html

0

Dopo la ricerca attraverso tutti i tipi di forum, ho appena fatto la seguente:

io chiamo lo showDialog (MyDialogID) E dismissDialog (MyDialogId) dal handleMessage (myMessage) Metodo dal mio gestore.

Prima ho chiamato showDialog nel mio metodo onCreate() e ho provato a chiudere la finestra di dialogo in handle-Message. Perché questo ha risolto il problema, non posso dire.

6

Mi sono imbattuto in questo quando mostro una finestra di dialogo nell'override onCreate dell'attività. Prova a spostare il codice che fa sì che la finestra di dialogo venga mostrata nell'override di onPostCreate. Questo sembra funzionare per me.

+0

Ho visto lo stesso problema con showDialog() in onCreate() - anche se questo sembra essersi verificato solo all'avvio dell'app tramite il debugger. Spostare showDialog() su onPostCreate() ha fatto il lavoro per me - grazie! – sstn

+0

Ottima soluzione, usa OnPostCreate per aprire la finestra di dialogo ... @Override public void onPostCreate (Bundle savedInstanceState) { super.onCreate (savedInstanceState); launch_app(); } –

+0

Questo è un bug Android documentato: http://code.google.com/p/android/issues/detail?id=24646 –

7

La soluzione migliore per me sembra utilizzare removeDialog (id) invece di dismissDialog(); Meno riutilizzo in questo modo, ma più sicuro (non gettare nulla) e nessun problema quando si cambia orientamento.

3

Dopo aver premuto il pulsante Home e aver effettuato l'accesso all'app morelocal (cambia lingua del dispositivo), quando sono tornato alla mia app, non è stato possibile chiudere nuove finestre di dialogo tramite dismissDialog (ho avviato la finestra di dialogo da activity onCreate).

La soluzione era chiamare removeDialog anziché dissmissDialog(). Questo è stato raccomandato da Harri sopra, molti thx.

ho creato un bug report Android:

13858


soluzione è quella di creare il dialogo con OnPostCreate invece di OnCreate. Ho aggiunto queste informazioni alla segnalazione del bug e ho consigliato di migliorare lo dialog documentation.

5

Ho perso più di un giorno su un problema di questo tipo con le finestre di dialogo che non venivano ignorate quando si chiama dismissDialog. Si è verificato dopo la mia prima rotazione dello schermo e non ha mai funzionato in seguito. Stavo usando un AsyncTask esterno a cui è stato passato un riferimento allo stato esplicitamente.

Alla fine la soluzione era davvero semplice ... removeDialog(int) anziché dismissDialog(int).

Avevo passato quello che mi sembrava di dimostrare per sempre che stavo facendo il licenziamento sulla corretta attività e controllando il numero di volte che le cose venivano chiamate ecc., Ma era causato da alcuni dei jiggerypokery dietro le quinte.

0

Stavo sperimentando lo stesso problema. Stavo creando un AlertDialog e un ProgressDialog all'interno del callback onCreateDialog() e li mostra dallo onCreate(). Creare queste finestre di dialogo direttamente in onCreate (senza utilizzare onCreateDialog()) e chiuderle in onPause() ha funzionato per me! Basato su 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(); 

    } 

} 
Problemi correlati