【问题标题】:This Handler class should be static or leaks might occur - custom Chronometer这个 Handler 类应该是静态的,否则可能会发生泄漏 - 自定义 Chronometer
【发布时间】:2020-09-06 08:08:39
【问题描述】:

首先,即使这个问题之前可能已经回答过,我仍然不知道如何解决这个问题,因为我从未使用过WeakReferences,尽管阅读了一些答案/示例,但我仍然不知道不知道怎么做。

我正在开发的应用程序将有一个显示分钟、秒和毫秒的 Chronometer,这是原始 Android Chronometer 无法做到的。所以我四处寻找一些替代品,发现了一个GitHub library,它本质上是一个改良的天文台。 导入库后,我注意到一个 Lint 警告说

这个 Handler 类应该是静态的,否则可能会发生泄漏(匿名 android.os.Handler)

在第 147 行:

private Handler mHandler = new Handler() {
    public void handleMessage(Message m) {
        if (mRunning) {
            updateText(SystemClock.elapsedRealtime());
            dispatchChronometerTick();
            sendMessageDelayed(Message.obtain(this , TICK_WHAT),
                    100);
        }
    }
};

看起来推荐的修复方法是创建 Handler 类 static 并使用 WeakReferences 访问 UI。所以,在用private static class mHandler extends Handler 替换private Handler mHandler = new Handler() 后,警告消失了……但现在出现了一些错误。 无法从静态上下文中引用布尔值 mRunning 以及方法 updateText(long)dispatchChronometerTick()

在将它们设为static 后,现在会出现更多相同但变量不同的错误。在也将它们设为static 之后,我有义务撤消我刚刚所做的,因为无法从静态上下文中引用setText(text);com.example.myapp.Chronometer.this,这将再次显示先前的错误;并制作sendMessageDelayed(android.os.Message, long)removeMessages(int) static,我相信这不能从代码中完成。 (点击链接看看我在说什么台词)。

因此,通过修复某些内容,其他地方会出现错误,我将不得不撤消我所做的。

如果有人能帮我解决这个问题,我将不胜感激。

【问题讨论】:

    标签: android


    【解决方案1】:

    首先,我们应该谈谈为什么 Android Studio 会警告这个消息。当您创建Handler() 并声明回调handleMessage。它是匿名类,它可以引用外部类的实例。当外部类死亡但回调仍然被调用时,这可能会泄漏。比如当你在Activity中声明回调handleMessage时可以调用你的Activitydestroy

    有两种方法可以修复它(我假设你在 Activity 中声明它)

    1. 忽略警告并在 onDestroy 内部调用 mHandler.removeCallbacksAndMessages(null)

    2. 像这样制作 MyHanler 类

        public class MyHandler extends Handler {
            private WeakReference<YourActivity> weakReference;
            public MyHandler(YourActivity activity) {
                weakReference = new WeakReference<YourActivity>(activity);
            }
    
            @Override
            public void handleMessage(Message msg) {
                if (weakReference != null && weakReference.get() != null) {
                    YourActivity activity = weakReference.get();
                    if (activity.mRunning) {
                        activity.updateText(SystemClock.elapsedRealtime());
                        activity.dispatchChronometerTick();
                        sendMessageDelayed(Message.obtain(this, TICK_WHAT),
                                100);
                    }
                }
            }
        }
    

    【讨论】:

    • 解释清楚,谢谢!警告现在消失了,我只需要将任何mHandler 引用更改为MyHandler()。但我决定使用另一个库,因为出于某种原因,这个库只计算毫秒。无论如何,由于您的示例,现在我对如何使用 weakReferences 有了一个想法。再次感谢!
    猜你喜欢
    • 2012-11-10
    • 2013-09-22
    • 2012-07-09
    • 1970-01-01
    • 2013-08-14
    • 2017-11-02
    • 2020-10-30
    相关资源
    最近更新 更多