【问题标题】:This Handler class should be static or leaks might occur: final Handler这个 Handler 类应该是静态的,否则可能会发生泄漏:final Handler
【发布时间】:2012-11-10 12:39:29
【问题描述】:

在下面的代码 Eclipse 生成警告“这个处理程序类应该是静态的,否则可能会发生泄漏”。

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())!

【问题讨论】:

标签: java android memory-leaks


【解决方案1】:

handler - 识别应该发生回调的线程的处理程序。如果为null,回调将从进程的线程池发生。

想象一下这种情况。一些活动调用PendingIntent.send(...) 并放入non-static inner subclass of Handler。然后活动被破坏。 但内心阶层生活

内部类仍然拥有指向已销毁活动的链接,它不能被垃圾回收。

因此您需要将其设为静态。

来源:Handlers and memory leaks in Android

【讨论】:

  • Shrikant,我之前读过这个话题。请在我的代码上下文中使用 handleMessage() 中的调用非静态方法...
  • 码猴叔的回答(来自我提供的链接)对你有帮助吗?
  • Code Uncle Code Monkey 很有帮助,但是当不存在时,在 handleMessage() 中调用非静态方法。当需要调用非静态时,他的代码不起作用。是不是我做错了什么?
【解决方案2】:

来自Android lint checks

处理程序泄漏 ------------ 摘要:确保 Handler 类不持有对 外层 优先级:4 / 10 严重性:警告 类别:性能 在 Android 中,处理程序类应该是静态的,否则可能会发生泄漏。留言 在应用程序线程的 MessageQueue 上排队也保留了它们的目标 处理程序。如果 Handler 是一个内部类,它的外部类将被保留为 好吧。为避免泄漏外部类,请将 Handler 声明为静态嵌套 具有对其外部类的 WeakReference 的类。

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

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

什么会阻止您的消息被处理?不幸的是,lint 工具无法解决这个问题,因此它总是警告您可能存在内存泄漏。如果您确定自己在做什么,可以通过various methods 隐藏这些消息。

对于您的情况,将Activity 设置为Runnable 看起来不是一个好主意,但无论如何您应该使用Handler.post 或最好的Activity.runOnUIThread

【讨论】:

    【解决方案3】:

    这是一个使用弱引用和静态处理程序类来解决 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);
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-09-22
      • 2012-07-09
      • 1970-01-01
      • 2013-08-14
      • 2020-09-06
      • 2017-11-02
      • 2020-10-30
      相关资源
      最近更新 更多