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

5
在下面的代码中,Eclipse会生成警告"This Handler class should be static or leaks might occur"。
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())!


这与此问题基本相同:https://dev59.com/T2gu5IYBdhLWcg3wUlnt - ThomasW
3个回答

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);
  }
}

2

handler - 标识回调应发生的线程的处理程序。 如果为空,则回调将从进程的线程池中发生。

设想一下情况。 一些Activity调用 PendingIntent.send(...) 并放了 非静态内部类的Handler子类。 然后活动被销毁。 但内部类还在

内部类仍然持有对已销毁活动的链接,因此无法进行垃圾回收。

因此您需要使其静态。

来源:Android中的Handlers和内存泄漏


Shrikant,我之前读过这个主题。请将其应用于我的代码上下文中,在handleMessage()中调用非静态方法... - Tapa Save
你从我提供的链接中查看了 Code Monkey 大叔的回答,是否有所帮助? - Shrikant Ballal
编程方面的内容翻译如下:Code Uncle Code Monkey很有帮助,但当在handleMessage()中调用非静态方法时不存在。当需要调用非静态方法时,他的代码不起作用。可能是我做错了什么? - Tapa Save

2
Android Lint检查中:
HandlerLeak ----------- 摘要:确保Handler类不会持有对外部类的引用
优先级:4/10 严重性:警告 类别:性能
在Android中,Handler类应该是静态的,否则可能会出现泄漏。在应用程序线程的MessageQueue上排队的消息也会保留它们的目标Handler。如果Handler是内部类,则其外部类也将被保留。为了避免泄漏外部类,将Handler声明为带有其外部类弱引用的静态嵌套类。
警告的第一部分是因为final Handler handler = new Handler()创建了一个匿名内部类。内部类无法单独创建,您总是需要一个外部实例。还记得如何在Java中创建这个 OuterClass.InnerClass innerObject = outerObject.new InnerClass();。每个内部类对象还必须保持对外部对象Outer.this的引用以访问外部成员。
第二部分是final Message message = handler.obtainMessage( 1, MyFunction( context));具有对您的内部处理程序类的句柄(它具有对外部Activity类的处理程序)。如果此消息的生存时间足够长,将无法释放Garbage Collect您的Activity。
什么可以阻止处理您的消息?不幸的是,Lint工具无法弄清楚这一点,因此它总是警告您可能会发生内存泄漏。如果您确定自己在做什么,则可以通过各种方法抑制这些消息。
对于您的情况,将Activity设置为Runnable看起来不是一个好主意,但无论如何,您应该使用Handler.post或最好的Activity.runOnUIThread

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