Wie bekomme ich den WindowLeaked Fehler weg?

  • 11 Antworten
  • Letztes Antwortdatum
T

txbarth

Ambitioniertes Mitglied
0
Hallo,
ich erhalte beim Schließen meiner App über das Menü einen WindowLeaked Fehler.

Code:
E/WindowManager: android.view.WindowLeaked: Activity MainActivity has leaked window android.widget.PopupWindow$PopupDecorView{276b0aa V.E...... ......ID 0,0-588,432} that was originally added here
                                                                       at android.view.ViewRootImpl.<init>(ViewRootImpl.java:386)
                                                                       at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:299)
                                                                       at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85) [....]

Code:
public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        switch (id) {
          case R.id.action_settings:
            Intent intent = new Intent(MainActivity.this, SettingsActivity.class);
            startActivity(intent);
            return true;

          case R.id.action_version:
            informVersion();
            return true;

          case R.id.action_close:
            end_notify_service = true;
            closeOptionsMenu(); 
            MainActivity.this.finish();

            return true;
          default:
            return super.onOptionsItemSelected(item);
        }
    }

Der Fehler tritt auf, wenn hier MainActivity.this.finish() aufgerufen wird und zwar dann am Ende von onDestroy. Der Fehler tritt aber nicht auf, wenn das Fenster über die Zurücktaste geschlossen und dadurch ebenfalls onDestroy aufgerufen wird. Was will das Ding von mir?
 
hallo txbarth,

ich habe zwar noch nie über diesen weg eine app abgeschossen, aber teste mal probeweise
tausche


MainActivity.this.finish();

mit



lg
Stefan

P.S Ist NUR eine Vermutung, wäre ziemlich brutal , aber wenns geht :)
 
was swa00 sagte würde ich auch probieren.
Ansonsten wenn du in der Main Aktivity bist dann
Code:
onBackPressed();
 
Oh mann, es funktioniert mit System.exit(0). Ich küsse deine Füße. Und vor allem bin ich damit ich noch ein ganz anderes schreckliches Problem losgeworden, das ich als nächstes angehen wollte. Ich hatte in den letzten 2 1/2 Wochen unter Linux/Eclipse das Data-Event-Management zwischen Server und Client App überarbeitet und ausgiebig getestet, und gestern abend die Klassen ins AS-Projekt eingebunden. Da musste ich dann feststellen, dass die App nur noch nach dem erstmaligen Aufruf nach einer Installation funktionierte. Bei erneuten Aufruf hing die App an bestimmten Stellen. Ich fing schon fast an zu heulen.

Kann es sein, dass das Android System statische Variablen und Objekte nach Programmende noch im Speicher hält, die in Konflikt geraten mit den Variablen / Objekten der neuen App-Instanz? System.exit(0) scheint ja alles richtig aufzuräumen.
 
txbarth schrieb:
Kann es sein, dass das Android System statische Variablen und Objekte nach Programmende noch im Speicher hält, die in Konflikt geraten mit den Variablen / Objekten der neuen App-Instanz? System.exit(0) scheint ja alles richtig aufzuräumen.

mit finish() schiesst du die App ja nicht ab, sie lebt noch .. - wenn auch nicht im Vordergrund

Du solltest in so einem Falle onResume() abfangen und deine Varibalen neu initialisieren ......
 
Zuletzt bearbeitet:
Der Hacken ist, dass die Activity geschlossen wird, aber an anderer Stelle noch ein View verändert wird. Der betroffene View wird wahrscheinlich das OptionMenu (ActionBar) sein.

Erklärung:
closeOptionsMenu(); - Die schließt das Menu (das dauert etwas, wg Animation (Thread))
MainActivity.this.finish(); Das beendet die Aktivity, bevor der oben gestartete Thread beendet wurde.

Das müsste zu den Fehler führen, da die Animation noch nicht beendet ist.
Kommentiere mal den Befehl closeOptionsMenu(); aus, und versuche es noch mal.

Statische Variablen bzw statische Objekte sollte man unter Java vermeiden. Wenn man so etwas braucht, hat man fast immer etwas vorher richtig falsch gemacht. Statische Variablen sind global. D.h. der Garbage Collector räumt diese nicht weg, sie bleiben immer im Speicher erhalten. Alle Referenzen von Objekten auf dieses Objekt bleiben auch erhalten.
Die Folge davon, das Objekte, die keine andere Referenz mehr habe, trotzdem nicht aus dem Speicher entfernt werden, da sie noch eine Referenz auf die statische Variable halten. Man hat ein Memory Leak.
Statische Variablen (nicht static final) sind wirklich nur das letzte Mittel. So etwas sollte man wirklich nur benutzen, wenn man mit seinen Latein am Ende ist.
 
markus.tullius schrieb:
Statische Variablen bzw statische Objekte sollte man unter Java vermeiden. Wenn man so etwas braucht, hat man fast immer etwas vorher richtig falsch gemacht. Statische Variablen sind global. D.h. der Garbage Collector räumt diese nicht weg, sie bleiben immer im Speicher erhalten. Alle Referenzen von Objekten auf dieses Objekt bleiben auch erhalten.
Die Folge davon, das Objekte, die keine andere Referenz mehr habe, trotzdem nicht aus dem Speicher entfernt werden, da sie noch eine Referenz auf die statische Variable halten. Man hat ein Memory Leak.
Statische Variablen (nicht static final) sind wirklich nur das letzte Mittel. So etwas sollte man wirklich nur benutzen, wenn man mit seinen Latein am Ende ist.


An der Stelle muss ich mich nochmals bei Markus bedanken - Nur mit seiner Hilfe habe ich als alter C'ler das nach langer Verzweiflung endlich mal kapiert und ist nun bei mir in Fleisch und Blut übergegangen - Danke nochmal an Dich lieber Markus
 
Ich verwende den Aufruf MainActivity.this.finish im Menü immer noch, da dies ja den Aufruf von onDestroy bewirkt und so noch alles, was läuft, ordentlich beendet werden kann (zB. Runnables / Timers). Dann ist das System.exit(0) nicht so "brachial", wenn eigentlich schon alles beendet ist.


Code:
case R.id.action_close:
            end_notify_service = true;
            closeOptionsMenu(); //war nur testweise eingefügt, eigentlich überflüssig
            MainActivity.this.finish();

Code:
 public void onDestroy() {
       super.onDestroy();

       [andere Dinge schließen, wenn offen]
        
        Data.deleteOldObserver(this);

        if(end_notify_service) {
          stopNotifyService();
          System.exit(0);
        }

    }

Mit statisch meinte ich aber als static final deklarierte Objekte / Variablen. Und es ist absolut legitim und richtig, diese jederzeit einsetzen zu können. Statische Variablen, Konstanten und Methoden in Java Sie sind global, also nicht an ein Objekt gebunden und existieren bis zum Programmende. Nur bin ich davon ausgegangen, dass eine Android-App beendet ist, wenn die offene MainActivity geschlossen und vorher z.B. ein laufender Service auch noch beendet wird. Mir war nicht klar, dass Android doch noch was im Speicher hält.
 
static final -> Konstante.

Und das ist was anderes als statische Variablen.
Variables (The Java™ Tutorials > Learning the Java Language > Language Basics)
Initializing Fields (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Deine Annahme über die Reihenfolge stimmt nur eingeschränkt. Zwar wird von der CPU ein Befehl nach dem anderen abgearbeitet. Aber manchmal möchte man nicht warten. Dafür gibt es Threads (Nebenläufigkeit) Damit kann man scheinbar mehrere Sachen gleichzeitig machen.
Android setzt Threads relativ häufig ein.
Rheinwerk Computing :: Java ist auch eine Insel – 14 Threads und nebenläufige Programmierung
 
markus.tullius schrieb:
static final -> Konstante.

Und das ist was anderes als statische Variablen.

Für mich ist das auch eine statische Variable. Konstante ist doch nichts anderes als eine nicht veränderbare statische Klassenvariable mit Großbuchstaben ;-)
 
static, final, public, usw sind einfach nur Modifikatoren. Und etwas, das static und final ist, ist nicht variabel. static heißt einfach, das man keine Instanz braucht, um es aufzurufen, und final, dass es nach der ersten Zuweisung nicht mehr geändert werden kann. Und so etwas nennt man normalerweise Konstante. Denn es fehlt die wichtigste Eigenschaft für ein Variable, der Wert kann nachträglich nicht mehr geändert werden.

Und System.exit(0) ist immer eine Gewaltakt. So ähnlich wie ein Auto, dass gegen die Mauer fährt. Es werden einfach alles unterbrochen. Im schlimmsten Fall Schreibvorgänge auf den Flashspeicher (z.B SQLite Datenbanken), wenn es dumm läuft sind alle Daten Schrott.
 
Und System.exit(0) ist immer eine Gewaltakt. So ähnlich wie ein Auto, dass gegen die Mauer fährt. Es werden einfach alles unterbrochen. Im schlimmsten Fall Schreibvorgänge auf den Flashspeicher (z.B SQLite Datenbanken), wenn es dumm läuft sind alle Daten Schrott.

@txbarth
Deswegen habe ich auch oben geschrieben :

P.S .... wäre ziemlich brutal , aber wenns geht :)
 
Zurück
Oben Unten