InputMethodManager引起的内存泄漏问题分析与解决

本文详细分析了由于InputMethodManager导致的内存泄漏问题,并探讨了常见解决方案的不足。通过研究源码,找到mCurRootView和mServedView/mNextServedView作为突破口,利用Java Reflection将它们置空,从而解决内存泄漏。然而,这种方法可能导致输入法无法显示。最后,通过改进方法,在确保不干扰其他界面的情况下,成功修复内存泄漏问题。
摘要由CSDN通过智能技术生成

问题重现:

static InputMethodManager.sInstance 

references InputMethodManager.mCurRootView(excluded)

references PhoneWindow$DecorView.mContext

leaks Activity.instance

网上的解决方案:

  1. @Override  
  2. public void onDestory() {  
  3.     //Fix memory leak: http://code.google.com/p/android/issues/detail?id=34731  
  4.     InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);  
  5.     imm.windowDismissed(this.getWindow().getDecorView().getWindowToken()); // hide method  
  6.     imm.startGettingWindowFocus(null); // hide method  
  7.     super.onDestory();  
  8. }  
这样解决仍然出现下面的问题:

但在实践中使用后,没有真正解决,Activity仍存在,但path to gc指向为unknown.如下图:

图3. Unknownpath

 

搜索来的代码不管用,就再想办法.

要想让Activity释放掉,思路就是将path togc这个链路剪断就可以.在这个bug中这个链路上有两个节点mContext(DecorView)和mCurRootView(InputMethodManager)可供考虑.下面思路就是从这两个节点中选择一个入手剪断path to gc即可.

阅读源码可知, DecorView继承自FrameLayout,mContext是其上下文环境,牵涉太多,不适合操作入手.mCurRootView在InputMehtodManager中的使用就简单得多了,在被赋值初始化后,被使用的场景只有一次判断及一次日志打印.所以这里选中mCurRootView为突破口.剪断其path to gc的操作为通过Java Reflection方法将mCurRootView置空即可(见文后代码).

编码实现后,再测,发现仍有泄露,但泄露情况有所变化,如下图:

图4. Leak path

         新的泄露点为mServedView/mNextServedView,可以通过同样的JavaReflection将其置空,剪断path to gc.但这里有个问题得小心,这里强制置空后,会不会引起InputMethodManager的NullPointerException呢?会不会引起系统内部逻辑崩溃?再次查阅源码,发现mServedView及mNextServedView在代码逻辑中一直有判空逻辑,所以这时就可以放心的强制置空来解决问题了.


图5. 判空逻辑

         最后贴出代码实现:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值