Diese Handler-Klasse sollte statisch sein oder es können Lecks auftreten: AsyncQueryHandler

8

Handler-Referenz-Leaks Da dieser Handler als innere Klasse deklariert ist, kann er verhindern, dass die äußere Klasse als Müll gesammelt wird. Wenn der Handler einen Looper oder eine MessageQueue für einen anderen Thread als den Hauptthread verwendet, gibt es kein Problem. Wenn der Handler den Looper oder die MessageQueue des Hauptthreads verwendet, müssen Sie die Handler-Deklaration wie folgt korrigieren: Deklarieren Sie den Handler als statische Klasse. Initiieren Sie in der äußeren Klasse eine WeakReference für die äußere Klasse, und übergeben Sie dieses Objekt an Ihren Handler, wenn Sie den Handler instanziieren. Nehmen Sie mithilfe des WeakReference-Objekts alle Verweise auf Member der äußeren Klasse vor.

Ich brauche eine Lösung !!!!!

%Vor%     
Nuno Malés 12.05.2016, 13:32
quelle

1 Antwort

20

Betrachten Sie den folgenden Code:

%Vor%

Obwohl dieser Code nicht offensichtlich ist, kann er zu einem massiven Speicherverlust führen. Android Lint gibt folgende Warnung:

%Vor%

Aber wo genau ist das Leck und wie könnte es passieren? Bestimmen wir die Ursache des Problems, indem wir zuerst dokumentieren, was wir wissen:

  1. Beim Start einer Android-Anwendung erstellt das Framework ein Looper-Objekt für den Hauptthread der Anwendung. Ein Looper implementiert eine einfache Nachrichtenwarteschlange, in der Nachrichtenobjekte nacheinander in einer Schleife verarbeitet werden. Alle wichtigen Anwendungsrahmenereignisse (z. B. Aktivitätslebenszyklusmethodenaufrufe, Schaltflächenklicks usw.) sind in Nachrichtenobjekten enthalten, die zur Nachrichtenwarteschlange des Looper hinzugefügt und einzeln verarbeitet werden. Der Looper des Hauptthreads ist während des gesamten Lebenszyklus der Anwendung vorhanden.
  2. Wenn ein Handler im Hauptthread instanziiert wird, ist er der Nachrichtenwarteschlange des Looper zugeordnet. Nachrichten, die an die Nachrichtenwarteschlange gesendet werden, enthalten einen Verweis auf den Handler, sodass das Framework Handler # handleMessage (Nachricht) aufrufen kann, wenn der Looper die Nachricht schließlich verarbeitet.
  3. In Java enthalten nicht statische innere und anonyme Klassen einen impliziten Verweis auf ihre äußere Klasse. Statische innere Klassen hingegen nicht.

Also wo genau ist der Speicherleck? Es ist sehr subtil, aber betrachten Sie den folgenden Code als Beispiel:

%Vor%

Wenn die Aktivität beendet ist, wird die verzögerte Nachricht für weitere 10 Minuten in der Nachrichtenwarteschlange des Hauptthreads gespeichert, bevor sie verarbeitet wird. Die Nachricht enthält einen Verweis auf den Handler der Aktivität, und der Handler enthält eine implizite Referenz auf seine äußere Klasse (in diesem Fall die SampleActivity). Diese Referenz bleibt bestehen, bis die Nachricht verarbeitet wird. Dadurch wird verhindert, dass der Aktivitätskontext als Garbage Collection erfasst wird und alle Ressourcen der Anwendung verloren gehen. Beachten Sie, dass dies auch für die anonyme Runnable-Klasse in Zeile 15 gilt. Nicht statische Instanzen anonymer Klassen enthalten eine implizite Referenz auf ihre äußere Klasse, sodass der Kontext verloren geht.

Um das Problem zu beheben, erstellen Sie eine Unterklasse des Handlers in einer neuen Datei oder verwenden Sie stattdessen eine statische innere Klasse. Statische innere Klassen enthalten keinen impliziten Verweis auf ihre äußere Klasse, daher wird die Aktivität nicht durchgelassen. Wenn Sie die Methoden der äußeren Aktivität innerhalb des Handlers aufrufen müssen, lassen Sie den Handler eine WeakReference für die Aktivität ausführen, damit Sie nicht versehentlich einen Kontext verlieren. Um das Speicherleck zu beheben, das auftritt, wenn wir die anonyme Runnable-Klasse instanziieren, machen wir die Variable zu einem statischen Feld der Klasse (da statische Instanzen anonymer Klassen keinen impliziten Verweis auf ihre äußere Klasse enthalten):

%Vor%

Der Unterschied zwischen statischen und nicht statischen inneren Klassen ist subtil, aber sollte jeder Android-Entwickler verstehen. Was ist das Endergebnis? Vermeiden Sie die Verwendung nicht-statischer innerer Klassen in einer Aktivität, wenn Instanzen der inneren Klasse den Lebenszyklus der Aktivität überstehen könnten. Stattdessen bevorzugen Sie statische innere Klassen und enthalten einen schwachen Verweis auf die darin enthaltene Aktivität.

    
shridutt kothari 12.05.2016, 13:41
quelle

Tags und Links