Android中的处理程序和内存泄漏

Ras*_*mus 46 android handler

请看下面的代码:

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;
        }}}};
         }
Run Code Online (Sandbox Code Playgroud)

当我使用这样的处理程序时,我得到一个警告"处理程序应该是静态的,否则它容易发生内存泄漏." 有人能告诉我这样做的最佳方法是什么?

Unc*_*key 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);
}
Run Code Online (Sandbox Code Playgroud)

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

  • 不应该在mFrag.get()之后检查以查看theFrag!= null,因为它可能会被垃圾收集. (13认同)

Tim*_*mmm 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);
}
Run Code Online (Sandbox Code Playgroud)

  • if(mReference.get()== null)返回; handleMessage(mReference.get(),msg); 这是一个糟糕的方法,因为在null检查和handleMessage之间,引用仍然可能是gc'ed导致空指针异常,因此它是一种更好的方法来将返回值存储在T reference = mReference.get(); 然后检查null并将局部变量传递给handleMessage方法. (4认同)

Geo*_*its 5

根据ADT 20的变化,看起来你应该把它变成静态的.

新的Lint检查:

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

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