Je développe une application Android 2.3.3 avec un service. J'ai ceci à l'intérieur de ce service pour communiquer avec l'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());
je reçois l'avertissement Lint suivant:
This Handler class should be static or leaks might occur: IncomingHandler
Qu'est-ce que ça veut dire?
Réponses:
Si la
IncomingHandler
classe n'est pas statique, elle aura une référence à votreService
objet.Handler
les objets pour le même thread partagent tous un objet Looper commun, dans lequel ils publient des messages et y lisent.Comme les messages contiennent la cible
Handler
, tant qu'il y a des messages avec le gestionnaire cible dans la file d'attente de messages, le gestionnaire ne peut pas être récupéré. Si le gestionnaire n'est pas statique, votreService
ouActivity
ne peut pas être récupéré, même après avoir été détruit.Cela peut entraîner des fuites de mémoire, du moins pendant un certain temps - tant que les messages restent dans la file d'attente. Ce n'est pas vraiment un problème à moins que vous ne publiez des messages retardés.
Vous pouvez rendre
IncomingHandler
statique et avoir unWeakReference
service à votre disposition:Voir cet article de Romain Guy pour plus de référence
la source
get()
renverra la valeur null lorsque l'objet référencé a été modifié. Dans ce cas, lorsque le service est mort.Comme d'autres l'ont mentionné, l'avertissement Lint est dû à une fuite de mémoire potentielle. Vous pouvez éviter l'avertissement Lint en passant un
Handler.Callback
lors de la constructionHandler
(c'est-à-dire que vous ne sousHandler
- classe pas et qu'il n'y a pas deHandler
classe interne non statique):Si je comprends bien, cela n'évitera pas la fuite de mémoire potentielle.
Message
les objets contiennent une référence à l'mIncomingHandler
objet qui contient une référence l'Handler.Callback
objet qui contient une référence à l'Service
objet. Tant qu'il y aura des messages dans laLooper
file d'attente de messages, leService
ne sera pas GC. Cependant, ce ne sera pas un problème grave, sauf si vous avez des messages à retard long dans la file d'attente de messages.la source
Voici un exemple générique d'utilisation d'une référence faible et d'une classe de gestionnaire statique pour résoudre le problème (comme recommandé dans la documentation Lint):
la source
Myclass
doit être déclarée aupublic Handler getHandler()
lieu depublic void
De cette façon, cela a bien fonctionné pour moi, maintient le code propre en gardant où vous gérez le message dans sa propre classe interne.
Le gestionnaire que vous souhaitez utiliser
La classe intérieure
la source
Avec l'aide de la réponse de @ Sogger, j'ai créé un gestionnaire générique:
L'interface:
Je l'utilise comme suit. Mais je ne suis pas sûr à 100% si cela est étanche. Peut-être que quelqu'un pourrait commenter ceci:
la source
Je ne suis pas sûr mais vous pouvez essayer d'initialiser le gestionnaire à null dans onDestroy ()
la source
Je suis confus. L'exemple que j'ai trouvé évite complètement la propriété statique et utilise le thread d'interface utilisateur:
Ce que j'aime dans cette solution, c'est qu'il n'y a aucun problème à mélanger les variables de classe et de méthode.
la source