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

时间:2013-08-13 10:18:31

标签: java android android-handler

我正在使用handler对象在单独的线程中完成耗时的任务后继续UI工作。有上述Lint警告的问题和跟随是我的方法。

[样本处理程序对象类型1] - >

Handler responseHandler = new Handler()
{
    @Override
    public void handleMessage(Message msg)
    {
        super.handleMessage(msg);
        Toast.makeText(MainActivity.this, "Finished the long running task in seperate thread...", Toast.LENGTH_LONG).show();
    }       
};

[样本处理程序对象类型2] - >

Handler responseHandler = new Handler(new Handler.Callback() 
{       
    @Override
    public boolean handleMessage(Message msg) 
    {   
        Toast.makeText(MainActivity.this, "Finished long running task in a seperate thread...", Toast.LENGTH_LONG).show();
        return false;      // RETURN VALUE ????
    }
});

在完成耗时任务的单独线程(UI除外)中,它执行以下行以将控件返回到UI线程(基本上是处理程序obj)。

responseHandler.sendEmptyMessage(0);

程序对两种类型的处理程序对象都很好用,但是对于第一种类型,我得到一个Lint警告说这个Handler类应该是静态的,否则可能会发生泄漏

因此我开始使用第二种类型的处理程序对象来避免Lint警告,但我遇到的问题是,我不确定返回值(true / false)的含义第二种方式,也适用于其中之一。我在google搜索了这么多,但没有得到一个确切的答案解释了这个返回值。

是的,我看到这个问题已经在stackoverflow中的很多地方被要求主要重写Lint警告,但我的问题主要是关于第二种方式的返回类型并且确认它是否正常我使用的方式解决问题第二种类型的处理程序Obj。

问题 - >

1)。有人知道 返回 值意味着什么(真/假)?

2)。我为摆脱棉绒警告而采取的措施是否正确?

...谢谢

2 个答案:

答案 0 :(得分:5)

每个处理程序都绑定到一个线程的Looper,每个Message都放在一个数据结构,一个消息队列中。

Message有一个target变量,指向Handlercallback变量指向Runnable

因此,如果您使用匿名类来创建Handler对象(如第一个示例中所示),那么知道匿名/非静态内部类是否包含对外部对象的引用(Activity?)。因此,队列中发布的消息可能会将Handler作为目标引用,Handler依次持有对外部类的引用,如Activity

现在,只要线程正在运行,消息就可以长时间保留在消息队列中。同时,该活动可能已经被驳回。但它不会被垃圾收集,因为消息具有模糊的间接引用。请注意,只要线程正在运行,Looper和Message Queue就会保持不变。

在第二个示例中,您没有创建匿名Handler类。您正在使用处理程序构造函数并将其传递给匿名Callback对象。这可能会阻止Lint抱怨,但我怀疑这是一个好方法。只需避免使用内部类,避免将Activity或上下文引用传递给Handler。

<强>更新

处理程序的dispatchMessage()获取将被处理的消息,其中它检查是否已提供回调,然后如果提供回调,则不会调用handleMessage(),如果回调的handleMessage() }返回true:

public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg); //--won't be called if you return true.
    }
}

答案 1 :(得分:1)

我发现内部类如处理程序有关内存泄漏的一些重要信息,并希望与您分享:

How to Leak a Context: Handlers & Inner Classes 我认为Handler类的重写方法不会返回任何内容,因为您可以检查: handleMessage()

你已经覆盖了Java Handler类而不是Android Handler,你可以看到Java Handler类的handleMessage()有return语句,你也可以在这里查看return语句的原因:boolean handleMessage(C context)