Android中的处理程序和内存泄漏

请看下面的代码:

public class MyGridFragment extends Fragment{ Handler myhandler = new Handler() { @Override public void handleMessage(Message message) { switch (message.what) { case 2: { ArrayList<HashMap<String,String>> theurls = (ArrayList<HashMap<String,String>>) message.obj; urls.addAll(theurls); theimageAdapter.notifyDataSetChanged(); dismissBusyDialog(); break; }}}}; } 

当我使用这样的处理程序时,我得到一个警告“处理程序应该是静态的,否则它容易发生内存泄漏”。 有人能告诉我什么是最好的办法吗?

我最近在自己的代码中更新了类似的东西。 我只是把匿名的Handler类变成了一个受保护的内部类,而且Lint警告消失了。 看看下面的代码是否适合你:

 public class MyGridFragment extends Fragment{ static class MyInnerHandler extends Handler{ WeakReference<MyGridFragment> mFrag; MyInnerHandler(MyGridFragment aFragment) { mFrag = new WeakReference<MyGridFragment>(aFragment); } @Override public void handleMessage(Message message) { MyGridFragment theFrag = mFrag.get(); switch (message.what) { case 2: ArrayList<HashMap<String,String>> theurls = (ArrayList<HashMap<String,String>>) message.obj; theFrag.urls.addAll(theurls); theFrag.theimageAdapter.notifyDataSetChanged(); theFrag.dismissBusyDialog(); break; }//end switch } } MyInnerHandler myHandler = new MyInnerHandler(this); } 

你可能不得不改变我把“碎片”放在哪里。 因为我只能猜测那些引用。

这是我可以使用的一个有点有用的小class。 可悲的是,它仍然非常冗长,因为你不能拥有匿名的静态内部类。

 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<MyFragment> * { * 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<T> extends Handler { private WeakReference<T> mReference; public WeakReferenceHandler(T reference) { mReference = new WeakReference<T>(reference); } @Override public void handleMessage(Message msg) { if (mReference.get() == null) return; handleMessage(mReference.get(), msg); } protected abstract void handleMessage(T reference, Message msg); } 

根据ADT 20更改 ,看起来应该将其设置为静态。

新皮特检查:

检查以确保Fragment类是可实例化的。 如果你不小心使一个片段的内部类是非静态的,或者忘记了有一个默认的构造函数,那么当系统在configuration改变后尝试重新实例化片段时,可能会遇到运行时错误。

查找处理程序泄漏:此检查可确保处理程序内部类不包含对其外部类的隐式引用。

如果您阅读有关AccountManager或PendingIntent的文档,您将看到有些方法将Handler作为参数之一。

例如 :

  • onFinished – 发送完成时要调用的对象,如果没有callback,则为null。
  • 处理程序 – 处理程序标识callback应该发生的线程 。 如果为null,callback将从进程的线程池中发生。

想象一下情况。 一些Activity调用PendingIntent.send(…)并放置Handler的非静态内部子类。 然后活动被破坏。 但内心阶层的生活。

内部类仍然有一个被破坏的活动的链接,它不能被垃圾收集。

如果你不打算把你的处理程序发送到这种方法,你没有什么可担心的。

我遇到了同样的问题,我发现这是一个有很多问题和答案的话题。 我的解决scheme很简单,我希望它可以帮助某人:

 /* BEFORE */ private Handler mHandler= new Handler() { @Override public void handleMessage(Message msg) { this.doSomething(); }; }; 

我们可以创build一个简单运行Runnable的静态Handler子类。 实际的处理程序实例将通过可以访问实例variables的runnable知道该怎么做。

 /* 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(); } }); 

警告已经消失,而function是相同的。