Cette classe de Gestionnaire doit être statique ou des fuites peuvent se produire: IncomingHandler
Je suis l'élaboration d'un Android 2.3.3 application d'un service. J'ai présent à l'intérieur de ce service pour communiquer avec activité Principale:
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());
[ ... ]
}
Et ici, final Messenger mMessenger = new Messenger(new IncomingHandler());
, j'ai le Charpie avertissement:
This Handler class should be static or leaks might occur: IncomingHandler
Ça veut dire quoi?
- Découvrez ce blog pour beaucoup plus d'informations sur ce sujet!
- Des fuites de mémoire, provoqué par la collecte des ordures... C'est assez pour montrer comment Java est incohérent et mal conçu
Vous devez vous connecter pour publier un commentaire.
Si
IncomingHandler
classe n'est pas statique, elle aura une référence à votreService
objet.Handler
objets pour le même thread tous partagent un Looper objet, qui de poster des messages et de la lecture.Que les messages contiennent des cibles
Handler
, tant qu'il y a des messages à la cible de gestionnaire dans la file d'attente de messages, le gestionnaire ne peut pas être nettoyée. Si le gestionnaire n'est pas statique, votreService
ouActivity
ne peut pas être nettoyée, même après avoir été détruit.Cela peut conduire à des fuites de mémoire, pour quelque temps du moins, tant que les messages restent int la file d'attente. Ce n'est pas vraiment un problème, à moins que vous publiez, longtemps retardée, messages.
Vous pouvez faire
IncomingHandler
statique et unWeakReference
à votre service:Voir ce post par Romain Guy pour de plus amples référence
mService.get() == null
? Qu'advient-il le message ? Est-il réellement possible de recevoir une valeur null à partir de mService.get() ?get()
sera de retour null lorsque l'objet référencé était gc-ed. Dans ce cas, lorsque le service est morte.mService = null;
est une erreur). Comme pour le pain, mettre lecode in service.handleMessage()
Comme d'autres l'ont mentionné les Peluches d'avertissement est en raison du risque de fuite de mémoire. Vous pouvez éviter les Peluches avertissement par le passage d'un
Handler.Callback
lors de la construction deHandler
(c'est à dire que vous n'avez pas de sous-classeHandler
et il n'y a pas deHandler
non-statique à l'intérieur de la classe):Si je comprends bien, ce ne sera pas éviter le risque de fuite de mémoire.
Message
objets contiennent une référence à lamIncomingHandler
objet qui contient une référence à laHandler.Callback
objet qui contient une référence à l'Service
objet. Tant qu'il y a des messages dans leLooper
message de la file d'attente, leService
ne sera pas en GC. Toutefois, il ne sera pas un problème grave, sauf si vous avez long délai d'attente de messages dans la file d'attente de messages.Ici est un exemple générique de l'utilisation d'une référence faible et statique de la classe de gestionnaire pour résoudre le problème (comme recommandé dans la Charpie de la documentation):
Myclass
doivent être déclarés commepublic Handler getHandler()
au lieu depublic void
De cette façon a bien fonctionné pour moi, maintient code propre en gardant où vous gérer le message dans sa propre classe.
Le gestionnaire vous souhaitez utiliser
L'intérieur de la classe
Avec l'aide de @Sogger réponse, j'ai créé un générique Gestionnaire:
L'interface:
Je l'utilise comme suit. Mais je ne suis pas sûr à 100% si c'est une fuite à la sécurité. Peut-être que quelqu'un pourrait faire un commentaire sur ce:
Je ne suis pas sûr, mais vous pouvez essayer intialising gestionnaire null dans onDestroy()