您现在的位置是:首页 > 文章详情

Android InputMethodManager内存泄漏

日期:2018-08-29点击:390

最近通过LeakCanary检测内存泄漏,发现一个很莫名其妙的问题,截图如下所示:


img_4998a3c709bb18b0fb8781525567e775.png
内存泄漏

从这里可以看到,InputMethodManager的mNextServedView持有了一个RecyclerView的引用,而RecyclerView则持有了IndexActivity的引用,从而导致了IndexActivity的内存泄漏。

据说这是输入法的一个bug,在LeakCanary上有个提到过这个问题(https://github.com/square/leakcanary/issues/572),但是该问题并不是一个普遍性的bug,而是部分机型上会出现。本人拿手头上的几台设备测试过,小米MIX2、小米红米5、三星Note3、三星Galaxy S7 edge、Vivo X9、Oppo R9还有一台华为设备忘记型号了,只有三星 Galaxy S7 edge上频繁出现InputMethodManager内存泄漏的问题。不得不说,谷歌的Android系统坑真是多,各种机型、各种分辨率,但是没办法,有坑我们也得一个一个去填。

查看InputMethodManager的源码可以看到以下定义:

 /** * This is the root view of the overall window that currently has input * method focus. */ View mCurRootView; /** * This is the view that should currently be served by an input method, * regardless of the state of setting that up. */ View mServedView; /** * This is then next view that will be served by the input method, when * we get around to updating things. */ View mNextServedView; 

通过LeakCanary的检测发现,发生内存泄漏时,这三者都有可能被InputMethodManager持有依赖引用,而View则一直被Activity持有引用,进而导致了Activity的内存泄漏。
那么怎么解决这个问题呢?参考了不少方案,发现还是采用反射来将这些依赖的View置空,手动切断对象的引用链最有效,具体代码如下:

public class MemoryLeakUtil { public static void fixInputMethodMemoryLeak(Context context) { if (context == null) return; InputMethodManager inputMethodManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); if (inputMethodManager == null) return; String[] viewArr = new String[]{"mCurRootView", "mServedView", "mNextServedView"}; Field field; Object fieldObj; for (String view : viewArr) { try { field = inputMethodManager.getClass().getDeclaredField(view); if (!field.isAccessible()) { field.setAccessible(true); } fieldObj = field.get(inputMethodManager); if (fieldObj != null && fieldObj instanceof View) { View fieldView = (View) fieldObj; if (fieldView.getContext() == context) { //注意需要判断View关联的Context是不是当前Activity,否则有可能造成正常的输入框输入失效 field.set(inputMethodManager, null); } else { break; } } } catch (Exception e) { e.printStackTrace(); } } } } 

在内存泄漏的Activity里增加:

 @Override protected void onDestroy() { //手动切断InputMethodManager里的View引用链 MemoryLeakUtil.fixInputMethodMemoryLeak(this); super.onDestroy(); } 
原文链接:https://yq.aliyun.com/articles/663989
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章