2009-05-21 7 views
22

Ich benutze die showDialog() und dismissDialog() um Fortschrittsdialoge in meiner App anzuzeigen. Von der Erstellung des Dialogfelds und dem Aufruf von show() darauf hin, diesen zu verwenden, um den Status beim Ändern der Ausrichtung zu speichern.Android - entlassenDialog nicht den Dialog

Aber wenn ich die Ausrichtung von Hoch-> Querformat-> Hochformat ändern, die dismissDialog() nicht mehr den Dialog. Der Dialog bleibt die ganze Zeit dort und ich muss den Zurück-Knopf drücken, damit er verschwindet.

Jeder Grund, warum es sich so verhalten würde?

bearbeiten

Um dieses Problem zu überwinden, habe ich versucht, einen removeDialog() in onDestroy() so fügte hinzu, dass der Dialog nicht erstellt wird/angezeigt zweimal und vor Orientierungsänderung, der Dialog entfernt wird. Versuchte Protokollanweisungen hinzufügen und sehen, was

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 

passiert, wenn wir hier sehen, zunächst, wenn die Aktivität angezeigt wird, wird die onCreateDialog einmal aufgerufen und auf die Ausrichtung ändern, onSaveInstanceState und onDestroy genannt werden.

Aber danach wird onCreateDialog zweimal aufgerufen (einmal durch einen Aufruf von showDialog, den ich mache, aber warum zum 2. Mal?) Und das passiert jedes Mal, wenn ich die Ausrichtung von daher ändere.

Eine Idee, warum das passiert?

Thanks again

+0

Kann mir bitte jemand mit diesem Problem helfen? Ich habe viele Posts und Blogs zu diesem Thema gesehen, aber keine scheint eine funktionierende Lösung zu haben. – lostInTransit

Antwort

0

Bitte beachten Sie, dass jedes Mal, wenn Sie die Ausrichtung ändern, eine neue Instanz Ihrer Activity (und damit Ihrer Dialog über onCreateDialog) erstellt wird. Sie können dies überprüfen, indem Sie in beiden Konstruktoren eine Protokollanweisung hinzufügen.

Obwohl schwer zu sagen, ohne einen Blick auf Ihren Code, ich schätze, Sie rufen dismissDialog auf einer älteren Instanz Ihres Activity.

Betrachten Sie die Activity folgende, die einfach eine leere Dialog zeigt, wenn eine Schaltfläche geklickt wird und startet eine TimerTask es nach 10 Sekunden zu entlassen:

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

Dieser Code ein Problem ähnlich dem hat Sie beschreiben : Wenn - während der 10 Sekunden - die Orientierung geändert wird, wird die Dialog nie entlassen. Warum? zum Zeitpunkt Da die TimerTask ist run, ein ganz anderer Satz von Test und Dialog Instanzen hat (während der Orientierungsänderung) erstellt worden ist und die TimerTask ‚s dialog Instanzvariable Referenzen einer Test Instanz, die von dem einen verschieden ist, die derzeit aktiv ist der Bildschirm.

Offensichtlich gibt es mehr Möglichkeiten, um mit diesem Problem zu befassen (meist je nach Anwendung), eine schnellen (dirty?) Weg, um den obigen Code zu beheben wäre, einfach das dialog Feld static zu machen:

private static Dialog dialog;
+0

Danke Josef. Aber wie du gesagt hast, ist die Reparatur eigentlich ein Hack! Ich denke daran, Dienste stattdessen zu verwenden. Bis der Dienst läuft, zeige ich den Dialog. Ist das der richtige Weg? – lostInTransit

+0

Es hängt wirklich von der Anwendung ab. Aber Sie haben recht, (sehr) lang andauernde Aufgaben sollten unbedingt in den Dienst gestellt werden. –

4

Ich bin kürzlich auch auf dieses Problem gestoßen.Ich habe eine Anwendung mit vielen Aktivitäten, die alle auf globale Objekte zugreifen müssen (Datenbankverbindungen, Datenlisten usw.), und so habe ich die Klasse Application überschrieben. Zu diesem Zweck erkannte ich, dass ich nur einen Verweis auf die letzte Instanz des Fortschrittsdialogs in meiner ausführbaren Datei benötigte, die ich benutzte, um den Dialog zu schließen. Das ist, was ich kam mit und es überlebt anmutig Telefon Neuausrichtungen:

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

.... random stuff here ....

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

Mein Thread hat eine mHandler.post (showProgressRunnable), wenn Die Aufgabe startet und führt dann eine mHandler.post (hideProgressRunnable) aus, wenn die Aufgabe beendet ist. Da der Verweis auf den letzten ProgressDialog jetzt in der Application-Klasse gespeichert ist, kann ich ihn zuverlässig schließen, da ich mich nicht mehr an einer alten Objektreferenz festhalte.

Verbindung für die Nachwelt: http://developer.android.com/reference/android/app/Application.html

0

Nachdem durch alle Arten von Foren gesucht, ich habe gerade folgende:

Ich nenne den Showdialog (MyDialogID) UND dismissDialog (MyDialogId) aus dem handelte (myMessage) Methode von meinem Handler.

Davor habe ich showDialog in meiner onCreate() - Methode aufgerufen und versucht, den Dialog in handle-Message zu schließen. Warum das das Problem gelöst hat, kann ich nicht sagen.

6

Ich bin darauf gestoßen, wenn ein Dialog in der OnCreate-Überschreibung der Aktivität angezeigt wird. Versuchen Sie, den Code, der dazu führt, dass der Dialog angezeigt wird, stattdessen in die OnPostCreate-Überschreibung zu verschieben. Das scheint für mich zu funktionieren.

+0

Ich sah das gleiche Problem mit showDialog() in onCreate() - obwohl dies nur beim Starten der App über den Debugger aufgetreten scheint. Moving showDialog() zu onPostCreate() hat den Job für mich erledigt - danke! – sstn

+0

Große Lösung, verwenden Sie einfach OnPostCreate, um den Dialog zu starten ... @Override öffentliche void onPostCreate (Bundle savedInstanceState) { super.onCreate (savedInstanceState); launch_app(); } –

+0

Dies ist ein dokumentierter Android-Fehler: http://code.google.com/p/android/issues/detail?id=24646 –

7

Die beste Lösung für mich scheint RemoveDialog (ID) anstelle von disneyDialog(); Weniger Wiederverwendung auf diese Weise, aber sicherer (wirft nichts) und keine Probleme beim Wechseln der Ausrichtung.

3

Nachdem ich die Home-Taste gedrückt und zur App morelocal navigiert habe (Gerätesprache ändern), konnten neue Dialoge nicht über den Befehl disadDialog geschlossen werden (ich habe den Dialog von der Aktivität onCreate gestartet).

Die Lösung war, removeDialog anstelle von dissmissDialog() aufzurufen. Dies wurde von Harri oben empfohlen, viele thx.

Ich habe ein Android-Bug-Report erstellt:

13858


Lösung ist Ihr Dialog mit OnPostCreate statt OnCreate zu erstellen. Ich fügte diese Informationen dem Fehlerbericht hinzu und empfahl, die dialog documentation zu verbessern.

5

Ich verschwendete mehr als einen Tag auf ein Problem wie dieses mit Dialogen, die nicht beim Aufrufen von findDialog gelöscht werden. Es trat nach meiner ersten Bildschirmdrehung auf und funktionierte nie danach. Ich hatte eine externe AsyncTask verwendet, die explizit an den Zustand verwiesen wurde.

Am Ende war die Lösung wirklich einfach .... removeDialog(int) statt dismissDialog(int).

Ich hatte ausgegeben, wie ich mich fühlte für immer mich zu beweisen Ich tat die Entlassung auf die richtige Aktivität und die Anzahl der Male, wie die Dinge usw. aufgerufen wurden, aber es wurde von einigen der Jiggerypokery hinter den Kulissen verursacht.

0

Ich experimentierte das gleiche Problem. Ich erstellte einen AlertDialog und einen ProgressDialog innerhalb des onCreateDialog() Rückrufs und zeigte sie von der onCreate(). Diese Dialoge direkt in onCreate (ohne onCreateDialog()) zu erstellen und sie in onPause() zu entlassen, funktionierte für mich! auf https://stackoverflow.com/a/5693467/955619 Basierend

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

    } 

}