LeakCanary报告InputMethodManager泄漏

8

我正在试图找出我的应用程序中的一个漏洞,但我不确定它来自哪里。

LeakCanary告诉我可以忽略它。这是正确的吗?

01-06 12:04:56.580 6935-9159/com.mypackage D/LeakCanary: * LEAK CAN BE IGNORED.
01-06 12:04:56.580 6935-9159/com.mypackage D/LeakCanary: * com.mypackage.ui.map.MapComponentFragment has leaked:
01-06 12:04:56.580 6935-9159/com.mypackage D/LeakCanary: * GC ROOT android.view.inputmethod.InputMethodManager$1.this$0 (anonymous class extends com.android.internal.view.IInputMethodClient$Stub)
01-06 12:04:56.580 6935-9159/com.mypackage D/LeakCanary: * references android.view.inputmethod.InputMethodManager.mCurRootView
01-06 12:04:56.580 6935-9159/com.mypackage D/LeakCanary: * references com.android.internal.policy.impl.PhoneWindow$DecorView.mContext
01-06 12:04:56.580 6935-9159/com.mypackage D/LeakCanary: * references com.mypackage.ui.MainActivity.mFragments
01-06 12:04:56.580 6935-9159/com.mypackage D/LeakCanary: * references android.app.FragmentManagerImpl.mAdded
01-06 12:04:56.580 6935-9159/com.mypackage D/LeakCanary: * references java.util.ArrayList.array
01-06 12:04:56.580 6935-9159/com.mypackage D/LeakCanary: * references array java.lang.Object[].[0]
01-06 12:04:56.580 6935-9159/com.mypackage D/LeakCanary: * leaks com.mypackage.ui.map.MapComponentFragment instance
01-06 12:04:56.580 6935-9159/com.mypackage D/LeakCanary: * Reference Key: 0790f013-1c87-4d5f-8c10-db277187e3ce
01-06 12:04:56.580 6935-9159/com.mypackage D/LeakCanary: * Device: samsung samsung SM-N910C treltexx
01-06 12:04:56.580 6935-9159/com.mypackage D/LeakCanary: * Android Version: 5.1.1 API: 22 LeakCanary: 1.4-SNAPSHOT 2714152
01-06 12:04:56.580 6935-9159/com.mypackage D/LeakCanary: * Durations: watch=5085ms, gc=149ms, heap dump=2562ms, analysis=10313ms

这段代码引起了多个泄露问题,但我已经修复了它们。但有一个泄露问题我解决不了。

有什么线索吗?

修改

还有一件事,如果我想要忽略它,应该怎么做?

.instanceField("android.view.inputmethod.InputMethodManager", "mCurRootView")

但仍在LeakCanary中显示

显然,这个泄漏是在AndroidExcludeRef中,但仍在报告中。 https://github.com/square/leakcanary/issues/322


有各种解决方案或变通方法:https://issuetracker.google.com/issues/37043700#comment17 https://issuetracker.google.com/issues/36950938 https://dev59.com/8m445IYBdhLWcg3wGWd7 - Mr-IDE
4个回答

4
/**
 * call this method in activity onDestroy() method.
*/
public static void fixInputMethod(Context context) {
    if (context == null) {
        return;
    }
    InputMethodManager inputMethodManager = null;
    try {
        inputMethodManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
    } catch (Throwable th) {
        th.printStackTrace();
    }
    if (inputMethodManager == null) {
        return;
    }
    Field[] declaredFields = inputMethodManager.getClass().getDeclaredFields();
    for (Field declaredField : declaredFields) {
        try {
            if (!declaredField.isAccessible()) {
                declaredField.setAccessible(true);
            }
            Object obj = declaredField.get(inputMethodManager);
            if (obj == null || !(obj instanceof View)) {
                continue;
            }
            View view = (View) obj;
            if (view.getContext() == context) {
                declaredField.set(inputMethodManager, null);
            } else {
                continue;
            }
        } catch (Throwable th) {
            th.printStackTrace();
        }
    }
}

3

奇怪的是,当我忽略它时,我会得到类似这样的其他错误。它们总是来自于这个片段。 - Marcel
这是 Android 框架中的一个 bug,很可能已经被报告并在下一个 Android 版本中得到修复。因此,您无法对此问题做出任何处理,所以应该忽略它。 - Sandro Machado
我理解了,但是当我忽略这个监听器时,在按钮中却会得到一个新的监听器,这让我感觉很奇怪... - Marcel
那个标签是 LEAK CAN BE IGNORED. 吗? - Sandro Machado
我找到了别人的原因,但我不能忽略这个。似乎PhoneWindows在活动被销毁后仍然保留对该活动的引用。如何避免出现这种泄漏。(请参见我的更新问题) - Marcel

2

是的,您可以忽略这个泄漏。解决上述泄漏的一种hacky方案,适用于所有版本,在此


2022年4月编辑:

中介故事的作者已删除,但解决方案是使用透明活动作为退出活动。


1
但是这种解决方案会有一个副作用,即在按下“最近使用的应用”按钮时,会破坏您应用程序的“截图”。您的应用程序截图将显示为空白黑色(或白色)屏幕,而不是显示实际屏幕内容。尽管DummyActivity完全透明,但仍然存在这个问题。 - Mr-IDE
1
404 - "作者已删除此 Medium 故事" - Leo supports Monica Cellio
据我记得,解决办法是创建一个虚拟的透明活动并将其用作退出活动。 - humble_wolf
链接显示已删除... - Renetik
@humble_wolf,多么“优雅”的解决方案啊,现在我明白为什么文章被删除了 ;) - Renetik

0

LeakCanary已经将此泄漏视为Android操作系统的故障。但是,它仍然发生,这让我很烦恼。如果有人想要修复它,有一个解决方法。

https://gist.github.com/pyricau/4df64341cc978a7de414

只需在您的Activity的onCreate方法中调用此方法即可:
IMMLeaks.fixFocusedViewLeak(getApplication());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接