S’il vous plaît jeter un oeil au code ci-dessous:
public class MyGridFragment extends Fragment{ Handler myhandler = new Handler() { @Override public void handleMessage(Message message) { switch (message.what) { case 2: { ArrayList<HashMap> theurls = (ArrayList<HashMap>) message.obj; urls.addAll(theurls); theimageAdapter.notifyDataSetChanged(); dismissBusyDialog(); break; }}}}; }
Lorsque j’utilise un gestionnaire comme celui-ci, je reçois un avertissement “le gestionnaire doit être statique, sinon il est sujet à des memory leaks”. Quelqu’un peut-il me dire quelle est la meilleure façon de le faire?
J’ai récemment mis à jour quelque chose de similaire dans mon propre code. Je viens juste de faire de la classe Handler anonyme une classe interne protégée et l’avertissement Lint est parti. Voir si quelque chose comme le code ci-dessous fonctionnera pour vous:
public class MyGridFragment extends Fragment{ static class MyInnerHandler extends Handler{ WeakReference mFrag; MyInnerHandler(MyGridFragment aFragment) { mFrag = new WeakReference (aFragment); } @Override public void handleMessage(Message message) { MyGridFragment theFrag = mFrag.get(); switch (message.what) { case 2: ArrayList> theurls = (ArrayList>) message.obj; theFrag.urls.addAll(theurls); theFrag.theimageAdapter.notifyDataSetChanged(); theFrag.dismissBusyDialog(); break; }//end switch } } MyInnerHandler myHandler = new MyInnerHandler(this); }
Vous devrez peut-être changer où je mets “theFrag”. comme je ne pouvais que deviner ce que ceux référencés.
Voici un petit cours quelque peu utile que vous pouvez utiliser. Malheureusement, il est encore assez verbeux car vous ne pouvez pas avoir de classes internes statiques anonymes.
import java.lang.ref.WeakReference; import android.os.Handler; import android.os.Message; /** A handler which keeps a weak reference to a fragment. According to * Android's lint, references to Handlers can be kept around for a long * time - longer than Fragments for example. So we should use handlers * that don't have strong references to the things they are handling for. * * You can use this class to more or less forget about that requirement. * Unfortunately you can have anonymous static inner classes, so it is a * little more verbose. * * Example use: * * private static class MsgHandler extends WeakReferenceHandler * { * public MsgHandler(MyFragment fragment) { super(fragment); } * * @Override * public void handleMessage(MyFragment fragment, Message msg) * { * fragment.doStuff(msg.arg1); * } * } * * // ... * MsgHandler handler = new MsgHandler(this); */ public abstract class WeakReferenceHandler extends Handler { private WeakReference mReference; public WeakReferenceHandler(T reference) { mReference = new WeakReference (reference); } @Override public void handleMessage(Message msg) { if (mReference.get() == null) return; handleMessage(mReference.get(), msg); } protected abstract void handleMessage(T reference, Message msg); }
Selon les modifications ADT 20 , il semble que vous deviez le rendre statique.
Nouveaux contrôles de peluches:
Vérifiez que les classes de fragment sont instantanables. Si vous faites accidentellement un fragment innerclass non statique ou si vous oubliez d’avoir un constructeur par défaut, vous pouvez générer des erreurs d’exécution lorsque le système tente de réinitialiser votre fragment après un changement de configuration.
Rechercher les fuites de gestionnaire: cette vérification permet de s’assurer qu’une classe interne de gestionnaire ne contient pas de référence implicite à sa classe externe.
Si vous lisez des documents sur AccountManager ou PendingIntent, vous verrez que certaines méthodes utilisent Handler comme argument.
Par exemple :
Imaginez la situation. Certaines activités appellent PendingIntent.send (…) et placent la sous-classe interne non statique de Handler. Et puis l’activité est détruite. Mais la classe intérieure vit.
La classe interne contient toujours un lien vers l’activité détruite, elle ne peut pas être collectée.
Si vous ne prévoyez pas d’envoyer votre gestionnaire à de telles méthodes, vous n’avez rien à craindre.
Je rencontre le même problème et je trouve que c’est l’un de ces sujets avec beaucoup de questions et peu de réponses. Ma solution est simple et j’espère qu’elle peut aider quelqu’un:
/* BEFORE */ private Handler mHandler= new Handler() { @Override public void handleMessage(Message msg) { this.doSomething(); }; };
Nous pouvons créer une sous-classe Handler statique qui exécute simplement un Runnable. L’instance de gestionnaire réelle saura quoi faire à travers l’exécutable qui aura access aux variables d’instance.
/* AFTER */ static class RunnableHandler extends Handler { private Runnable mRunnable; public RunnableHandler(Runnable runnable) { mRunnable = runnable; } @Override public void handleMessage(Message msg) { mRunnable.run(); }; } private RunnableHandler mHandler = new RunnableHandler(new Runnable() { @Override public void run() { this.doSomething(); } });
L’avertissement est parti alors que la fonctionnalité est la même.