2012-10-23 2 views
6

ich eine Aktivität haben, die wie folgt aussieht:Speicherleck in android.os.Message und/oder Handler.removeCallback?

class MyActivity extends Activity { 
    Runnable refreshTimer = new Runnable() { 
     public void run() { 
      refresh(); 
     } 
    }; 

    protected onCreate(...) { 
     handler.postAtTime(refreshTimer, ...); 
    } 

    protected onDestroy() { 
     handler.removeCallbacks(refreshTimer); 
    } 

    protected void refresh() { ... } 
} 

Nach onDestroy genannt wird, gibt es immer noch Nachrichten in der Messageaktivität, die Verweise auf MyActivity $ 0 (die Refresh-Runnable) aus irgendeinem Grund enthalten. Da MyActivity $ 0 einen impliziten Verweis auf MyActivity hat, verursacht das einen Speicherverlust des MyActivity-Kontext. Eclipse-Memory Analyzer-Tool

Das Ergebnis merge_shortest_paths für android.app.Activity Phantom ohne, weich, schwach, usw. Referenzen mit: enter image description here

(Der Quellcode oben ist eine Vereinfachung der tatsächlichen Objektbeziehung angezeigt in der MAT-Dump)

Sollte nicht Aufruf removeCallbacks alle Verweise auf die ausführbaren Objekte aus der Warteschlange entfernen? Warum lecke ich Zusammenhänge?

Antwort

2

Etwas zu versuchen:

Nach dem Android-docs:

OnDestroy: Der letzte Anruf erhalten Sie vor Ihrer Aktivität zerstört wird. Dies kann entweder geschehen, weil die Aktivität beendet wird (jemand namens finish()) oder weil das System diese Instanz der Aktivität vorübergehend platzsparend zerstört.Sie ​​können diese beiden Szenarien mit der isFinishing() -Methode unterscheiden:

Wenn Sie Ihre Aktivitäten sind Verlassen sieht es aus wie es noch eine Reihe von Warteschlange Meldungen und der Kontext für das aufheben der Registrierung ist, wird den Abbruch Rückruf nicht aufgerufen werden

Was sollten Sie tun deregistrieren ist Ihr runnable in onPause. Diese Callback wird meistens verwendet, um einen persistenten Zustand zu speichern, den die Aktivität bearbeitet, um dem Benutzer ein "Edit in Place" -Modell zu präsentieren und sicherzustellen, dass nichts verloren geht, wenn nicht genügend Ressourcen vorhanden sind, um die ne zu starten w Aktivität, ohne diese zuerst zu töten. Dies ist auch ein guter Ort, um Dinge wie Animationen und andere Dinge zu stoppen, die eine merkliche Menge an CPU verbrauchen, um so schnell wie möglich zur nächsten Aktivität zu wechseln oder um Ressourcen zu schließen, die exklusiven Zugriff wie die Kamera haben.

Typischerweise wird ein Receiver oder „Scheduled“ Runnable in onResume registrieren, und in onPause für eine bessere Lebenszyklus Paarung

Ohne deregistrieren zu sehen, was Sie in refresh tun, ist es schwierig, zu sagen, es durch undichte werden könnte, um Aktivitätsreferenzen, bei denen es sich um Aktivitätsbereiche handelt, auf die in der Aktualisierungsmethode verwiesen wird.