此 Handler 类应该是静态的,否则可能会发生内存泄漏(空值)。

3
This Handler class should be static or leaks may occur (null)

这条消息是否指的是这里的“class”是“MyActivity”,因为Handler是一个对象,而我已经声明它是静态的。我应该忽略它还是需要在“MyActivity”声明中添加类似“static”的内容(我尝试过这样做,但出现了错误)。我注意到“弱引用”经常被建议用于此lint警告。
public class MyActivity extends Activity{
...
static Handler handler;
...
handler = new Handler()
  {
    public void handleMessage(Message msg) {

1
不,如果您实例化内部处理程序类,则应使类本身为静态以避免泄漏。现在,您正在使用默认的类构造函数,该构造函数不是静态的,您可以创建自己的内部类,该类扩展处理程序并且是静态的以修复警告。 - zgc7009
2
只有在使用任何类型的“延迟”执行并且未在末尾清空消息队列时,才存在“可能发生泄漏”的风险。 - pskink
2个回答

27

由于Handler是一个对象,而且我已经将其声明为静态的

你声明了数据成员为静态的,但是你正在使用匿名内部类,因此你的Handler子类不是static

应该这样做:

  handler = new Handler() {
    public void handleMessage(Message msg) {
      // do cool stuff
    }
  };

使用:

handler=new MyVeryOwnHandler();

其中MyVeryOwnHandler是一个普通的Java类或者是一个静态内部类:

private static class MyVeryOwnHandler extends Handler {
  public void handleMessage(Message msg) {
      // do cool stuff
  }
};

请注意,错误在于需要将 class 设为 static;它并没有说需要将 object 设为 static


感谢您对此错误的简明解释以及应该做什么的示例。我发现一个优雅的例子胜过千言万语。当我尝试添加“private”或“static”时,出现了“修改器静态不允许在这里”的错误,但是只使用“class MyVeryOwnHandler extends Handler”就可以消除泄漏警告。 - Androidcoder
1
@michael:如果MyVeryOwnHandler是自己的顶级Java类,在一个名为MyVeryOwnHandler.java的文件中,您将不需要(或不允许使用)privatestatic。但是,如果MyVeryOwnHandlerMyActivity的内部类,则privatestatic变得相关。 - CommonsWare
在我的主活动的onCreate中声明MyHandler时,它不允许我使用“static”或“private”,尽管仅创建新类而不使用“private”或“static”可以消除错误警告。我在这里找到了一篇有趣的文章:http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html,但他们的解决方案更加复杂。在onCreate之外声明该类是不方便的,因为我的处理程序涉及广告视图、应用内购买、插页式广告、排行榜等,必须重新声明为静态,并且某些方法无法识别。 - Androidcoder
@michael:“在我的主活动的onCreate中声明MyHandler时,它不允许我使用'static'或'private'”--那是因为从我的答案中,MyVeryOwnHandler没有在onCreate()中定义。它在onCreate()中被实例化。但是,它在活动的任何方法之外定义,因为这是在Java中定义静态和内部类的方式。 - CommonsWare
非常感谢。我希望在onCreate中定义新类,因为我必须处理它所涉及的所有事情,并使用“static private Handler handler”声明处理程序将使其更好,尽管从我所读到的内容来看,它仍然可能会泄漏。无论如何,我不使用延迟操作或大量的多重消息传递。我可能需要尝试Julianemailde下面的答案,以保持处理程序类在onCreate中。 - Androidcoder
@michael:“使用'static private Handler handler'”--不,那会让事情变得更糟。在这里,static Handler是指可以是常规Java类或static内部类。 - CommonsWare

4
为了避免内存泄漏,我也迁移到了静态嵌套类。Android Studio的解释可能有所帮助:

由于此Handler被声明为内部类,可能会防止外部类被垃圾回收。如果Handler正在使用除主线程之外的线程的Looper或MessageQueue,则没有问题。如果Handler正在使用主线程的Looper或MessageQueue,则需要修复Handler声明,步骤如下:将Handler声明为静态类;在外部类中,实例化对外部类的WeakReference,并在实例化Handler时将此对象传递给Handler;使用WeakReference对象引用外部类成员。

在迁移之前,我使用了developer.android.com建议的Looper线程实现,最终导致了警告。
  class LooperThread extends Thread {
  public Handler mHandler;

  public void run() {
      Looper.prepare();

      mHandler = new Handler() {
          public void handleMessage(Message msg) {
              // process incoming messages here
          }
      };

      Looper.loop();
  }  
 }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接