此Handler类应该是静态的,否则可能会发生泄漏:final Handler

时间:2012-11-22 06:47:34

标签: java android memory-leaks

在下面的代码中,Eclipse生成警告“此Handler类应该是静态的,否则可能会发生泄漏”。

public class MyActivity extends Activity implements Runnable
 {
   final Handler handler = new Handler()
    {
      @Override
      public void handleMessage( Message message)
       {
         String sResult = (String) message.obj;
         if( (sResult != null) && (sResult != ""))
           {
             MyNonStatic = (TableLayout) findViewById( R.id.tableLayout); // any non-static method
           }
         return;
       }
    };


   public void run()
    {
      final Message message = handler.obtainMessage( 1, MyFunction( context));
      handler.sendMessage( message);
    }

   public String MyFunction( Context context)
    {
      return "MyNewString";
    }
  }

我在网站上查看了很多主题,但没有得到解决方案。请帮我这个代码吗?

添加:我需要在handleMessage()中调用非静态方法(例如findViewById())!

3 个答案:

答案 0 :(得分:5)

以下是使用弱引用和静态处理程序类来解决Lint文档中建议的问题的示例:

public class MyClass{

  //static inner class doesn't hold an implicit reference to the outer class
  private static class MyHandler extends Handler {
    //Using a weak reference means you won't prevent garbage collection
    private final WeakReference<MyClass> myClassWeakReference; 

    public MyHandler(MyClass myClassInstance) {
      myClassWeakReference = new WeakReference<MyClass>(myClassInstance);
    }

    @Override
    public void handleMessage(Message msg) {
      MyClass myClass = myClassWeakReference.get();
      if (myClass != null) {
        ...do work here...
      }
    }
  }

  private final MyHandler mHandler = new MyHandler(this);

  public MyHandler getHandler() {
    return new MyHandler(this);
  }
}

答案 1 :(得分:2)

handler - 处理程序,用于标识应在其上进行回调的线程。如果为null,则回调将从进程的线程池发生。

想象一下情况。某些活动会调用PendingIntent.send(...)并放置non-static inner subclass of Handler。然后活动被摧毁。 但是内在的生活

内部类仍然拥有被破坏活动的链接,不能进行垃圾回收。

因此你需要让它变得静止。

来源:Handlers and memory leaks in Android

答案 2 :(得分:2)

来自Android lint checks

HandlerLeak
-----------
Summary: Ensures that Handler classes do not hold on to a reference to an
outer class

Priority: 4 / 10
Severity: Warning
Category: Performance

In Android, Handler classes should be static or leaks might occur. Messages
enqueued on the application thread's MessageQueue also retain their target
Handler. If the Handler is an inner class, its outer class will be retained as
well. To avoid leaking the outer class, declare the Handler as a static nested
class with a WeakReference to its outer class.

警告的第一部分是因为final Handler handler = new Handler()创建了一个匿名内部类。内部类不能以独立方式创建,您始终需要外部实例。记住如何在Java OuterClass.InnerClass innerObject = outerObject.new InnerClass();中创建它。每个内部类对象还必须保持对外部对象Outer.this的引用以访问外部成员。

第二部分是final Message message = handler.obtainMessage( 1, MyFunction( context));,它有一个内部处理程序类的句柄(它有一个外部Activity类的处理程序)。如果此消息的存在时间足够长,则无法对您的活动进行垃圾回收。

什么可以阻止正在处理的邮件?不幸的是,lint工具无法解决这个问题,所以它总是警告你可能存在内存泄漏。如果您确定自己在做什么,可以various methods禁止这些消息。

对于您的情况,将Activity设为Runnable似乎不是一个好主意,但无论如何可能应该使用Handler.post或最佳Activity.runOnUIThread