48

请看下面的代码:

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

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

4

6 回答 6

101

我最近在自己的代码中更新了类似的内容。我刚刚将匿名 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);
}

您可能需要更改我放置“theFrag”的位置。因为我只能猜测那些引用的内容。

于 2012-07-05T01:12:00.243 回答
11

这是我制作的一个有用的小类,你可以使用。遗憾的是它仍然很冗长,因为你不能有匿名的静态内部类。

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);
}
于 2012-11-21T12:52:59.517 回答
5

根据ADT 20 Changes,看起来您应该将其设为静态。

新的皮棉检查:

检查以确保 Fragment 类是可实例化的。如果您不小心使片段内部类成为非静态的,或者忘记了默认构造函数,则当系统在配置更改后尝试重新实例化片段时,您可能会遇到运行时错误。

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

于 2012-07-03T05:12:53.790 回答
4

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

例如

  • onFinished - 发送完成时回调的对象,或 null 表示没有回调。
  • handler -处理程序,标识应该发生回调的线程。如果为 null,则回调将从进程的线程池中发生。

想象一下情况。有的Activity调用PendingIntent.send(...),放入Handler的非静态内部子类。然后活动被破坏。但是内部阶级生活。

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

如果您不打算将处理程序发送到此类方法,则无需担心。

于 2012-07-03T12:10:43.420 回答
0

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

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

我们可以创建一个简单地运行 Runnable 的静态 Handler 子类。实际的处理程序实例将通过可以访问实例变量的可运行程序知道要做什么。

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

在功能相同的情况下,警告消失了。

于 2012-07-05T10:27:26.233 回答
0

这种情况的一个简单解决方案可能是:

Handler handler=new Handler(new Handler.Callback() {
    @Override
    public boolean handleMessage(Message message) {
        //do your stuff here
        return false;
    } });
于 2018-09-13T07:50:02.870 回答