android inputmethodmanager内存泄露,Android InputMethodManager内存泄漏

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

f2aa4cf53abd?utm_source=desktop&utm_medium=timeline

内存泄漏

从这里可以看到,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();

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值