Ich entwickle eine Android 2.3.3-Anwendung mit einem Dienst. Ich habe dies in diesem Dienst, um mit der Hauptaktivität zu kommunizieren:
public class UDPListenerService extends Service
{
private static final String TAG = "UDPListenerService";
//private ThreadGroup myThreads = new ThreadGroup("UDPListenerServiceWorker");
private UDPListenerThread myThread;
/**
* Handler to communicate from WorkerThread to service.
*/
private Handler mServiceHandler;
// Used to receive messages from the Activity
final Messenger inMessenger = new Messenger(new IncomingHandler());
// Use to send message to the Activity
private Messenger outMessenger;
class IncomingHandler extends Handler
{
@Override
public void handleMessage(Message msg)
{
}
}
/**
* Target we publish for clients to send messages to Incoming Handler.
*/
final Messenger mMessenger = new Messenger(new IncomingHandler());
[ ... ]
}
Und hier final Messenger mMessenger = new Messenger(new IncomingHandler());
bekomme ich folgende Lint-Warnung:
This Handler class should be static or leaks might occur: IncomingHandler
Was bedeutet das?
Antworten:
Wenn
IncomingHandler
Klasse nicht statisch ist, enthält sie einen Verweis auf IhrService
Objekt.Handler
Objekte für denselben Thread haben alle ein gemeinsames Looper-Objekt, an das sie Nachrichten senden und von denen sie lesen.Da Nachrichten ein Ziel enthalten
Handler
, kann der Handler nicht mit Müll gesammelt werden, solange sich Nachrichten mit dem Zielhandler in der Nachrichtenwarteschlange befinden. Wenn der Handler nicht statisch ist, ist IhrService
oderActivity
lässt sich nicht Müll gesammelt, auch nach zerstört.Dies kann zumindest für einige Zeit zu Speicherverlusten führen - solange die Nachrichten in der Warteschlange bleiben. Dies ist kein großes Problem, es sei denn, Sie veröffentlichen lange verzögerte Nachrichten.
Sie können
IncomingHandler
statisch machen und einenWeakReference
zu Ihrem Dienst haben:Siehe diesen Beitrag von Romain Guy für weitere Referenz
quelle
get()
gibt null zurück, wenn das referenzierte Objekt gc-ed wurde. In diesem Fall, wenn der Dienst unterbrochen ist.Wie andere bereits erwähnt haben, ist die Lint-Warnung auf den möglichen Speicherverlust zurückzuführen. Sie können die Lint-Warnung vermeiden, indem Sie
Handler.Callback
beim Konstruieren ein übergebenHandler
(dh Sie haben keine UnterklasseHandler
und es gibt keineHandler
nicht statische innere Klasse):So wie ich es verstehe, wird dies den möglichen Speicherverlust nicht vermeiden.
Message
Objekte enthalten eine Referenz auf dasmIncomingHandler
Objekt, das eine Referenz enthält. DasHandler.Callback
Objekt enthält eine Referenz auf dasService
Objekt. Solange sich Nachrichten in derLooper
Nachrichtenwarteschlange befinden,Service
ist dies kein GC. Es wird jedoch kein ernstes Problem sein, es sei denn, Sie haben Nachrichten mit langer Verzögerung in der Nachrichtenwarteschlange.quelle
Hier ist ein allgemeines Beispiel für die Verwendung einer schwachen Referenz- und statischen Handlerklasse zur Behebung des Problems (wie in der Lint-Dokumentation empfohlen):
quelle
Myclass
sollte jedoch alspublic Handler getHandler()
anstelle vonpublic void
Diese Methode hat bei mir gut funktioniert und den Code sauber gehalten, indem Sie die Stelle, an der Sie die Nachricht verarbeiten, in einer eigenen inneren Klasse aufbewahren.
Der Handler, den Sie verwenden möchten
Die innere Klasse
quelle
Mit Hilfe der Antwort von @ Sogger habe ich einen generischen Handler erstellt:
Die Schnittstelle:
Ich benutze es wie folgt. Ich bin mir aber nicht 100% sicher, ob dies auslaufsicher ist. Vielleicht könnte jemand dies kommentieren:
quelle
Ich bin nicht sicher, aber Sie können versuchen, den Handler in onDestroy () auf null zu setzen.
quelle
Ich bin verwirrt. Das Beispiel, das ich gefunden habe, vermeidet die statische Eigenschaft vollständig und verwendet den UI-Thread:
Was mir an dieser Lösung gefällt, ist, dass es kein Problem gibt, Klassen- und Methodenvariablen zu mischen.
quelle