[Android] InputMethodManager内存泄露现象及解决 输入法造成的内存泄露
2017-01-04 20:04
701 查看
当遇到这个输入法造成的内存泄露的时候,我表示一脸惊讶,因为我整个Activity中没有如何一个输入类控件,更不存在使用输入键盘。但是内存就这样不知不觉的泄露了。既然遇到了问题,我们就要寻求解决方案。
先看一下内存泄露对象InputMethodManager的引用路径
要想让Activity释放掉,思路就是将path togc这个链路剪断就可以.在这个bug中这个链路上有两个节点mContext(DecorView)和 mCurRootView(InputMethodManager)可供考虑.下面思路就是从这两个节点中选择一个入手剪断path to gc即可.
阅读源码可知, DecorView继承自FrameLayout,mContext是其上下文环境,牵涉太多,不适合操作入手.mCurRootView在InputMehtodManager中的使用就简单得多了,在被赋值初始化后,被使用的场景只有一次判断及一次日志打印.所以这里选中mCurRootView为突破口.剪断其path to gc的操作为通过Java Reflection方法将mCurRootView置空即可(见文后代码).
编码实现后,再测,发现仍有泄露,但泄露情况有所变化,如下图:
新的泄露点为mServedView/mNextServedView,可以通过同样的JavaReflection将其置空,剪断path to gc.但这里有个问题得小心,这里强制置空后,会不会引起InputMethodManager的NullPointerException呢?会不会引起系统内部逻辑崩溃?再次查阅源码,发现mServedView及mNextServedView在代码逻辑中一直有判空逻辑,所以这时就可以放心的强制置空来解决问题了.
为了让输入法在特定的Activity中置空,在其他的Activity中显示,我们需要做判断。fixInputMethodManagerLeak(ContextdestContext)方法参数中将目标要销毁的Activity A作为参数传参进去。在代码中,去获取InputMethodManager的关联View,通过View.getContext()与Activity A进行对比,如果发现两者相同,就表示需要回收;如果两者不一样,则表示有新的界面已经在使用InputMethodManager了,直接不处理就可以了。
下面写一个InputMethodManager工具类来处理内存泄露,下面直接贴代码:
直接在内存泄露的Activity的onDestory()方法中执行该方法:
参考文章:
[Android][Memory Leak] InputMethodManager内存泄露现象及解决
先看一下内存泄露对象InputMethodManager的引用路径
要想让Activity释放掉,思路就是将path togc这个链路剪断就可以.在这个bug中这个链路上有两个节点mContext(DecorView)和 mCurRootView(InputMethodManager)可供考虑.下面思路就是从这两个节点中选择一个入手剪断path to gc即可.
阅读源码可知, DecorView继承自FrameLayout,mContext是其上下文环境,牵涉太多,不适合操作入手.mCurRootView在InputMehtodManager中的使用就简单得多了,在被赋值初始化后,被使用的场景只有一次判断及一次日志打印.所以这里选中mCurRootView为突破口.剪断其path to gc的操作为通过Java Reflection方法将mCurRootView置空即可(见文后代码).
编码实现后,再测,发现仍有泄露,但泄露情况有所变化,如下图:
新的泄露点为mServedView/mNextServedView,可以通过同样的JavaReflection将其置空,剪断path to gc.但这里有个问题得小心,这里强制置空后,会不会引起InputMethodManager的NullPointerException呢?会不会引起系统内部逻辑崩溃?再次查阅源码,发现mServedView及mNextServedView在代码逻辑中一直有判空逻辑,所以这时就可以放心的强制置空来解决问题了.
为了让输入法在特定的Activity中置空,在其他的Activity中显示,我们需要做判断。fixInputMethodManagerLeak(ContextdestContext)方法参数中将目标要销毁的Activity A作为参数传参进去。在代码中,去获取InputMethodManager的关联View,通过View.getContext()与Activity A进行对比,如果发现两者相同,就表示需要回收;如果两者不一样,则表示有新的界面已经在使用InputMethodManager了,直接不处理就可以了。
下面写一个InputMethodManager工具类来处理内存泄露,下面直接贴代码:
package com.hwapu.education.teacher.utils; import java.lang.reflect.Field; import android.content.Context; import android.view.View; import android.view.inputmethod.InputMethodManager; /** * @author tangdekun * 用于输入法管理 */ public class InputMethodManagerUtils { /** * @param destContext 上下文对象 * 用于解决输入法内存泄露 * 参考:http://blog.csdn.net/sodino/article/details/32188809 */ public static void fixInputMethodManagerLeak(Context destContext) { if (destContext == null) { return; } InputMethodManager imm = (InputMethodManager) destContext.getSystemService(Context.INPUT_METHOD_SERVICE); if (imm == null) { return; } String [] arr = new String[]{"mCurRootView", "mServedView", "mNextServedView"}; Field f = null; Object obj_get = null; for (int i = 0;i < arr.length;i ++) { String param = arr[i]; try{ f = imm.getClass().getDeclaredField(param); if (f.isAccessible() == false) { f.setAccessible(true); } // author: sodino mail:sodino@qq.com obj_get = f.get(imm); if (obj_get != null && obj_get instanceof View) { View v_get = (View) obj_get; if (v_get.getContext() == destContext) { // 被InputMethodManager持有引用的context是想要目标销毁的 f.set(imm, null); // 置空,破坏掉path to gc节点 } else { // 不是想要目标销毁的,即为又进了另一层界面了,不要处理,避免影响原逻辑,也就不用继续for循环了 break; } } }catch(Throwable t){ t.printStackTrace(); } } } }
直接在内存泄露的Activity的onDestory()方法中执行该方法:
@Override protected void onDestroy() { // TODO Auto-generated method stub InputMethodManagerUtils.fixInputMethodManagerLeak(this); super.onDestroy(); }
参考文章:
[Android][Memory Leak] InputMethodManager内存泄露现象及解决
相关文章推荐
- Android中使用Handler造成内存泄露的分析和解决
- Android中使用Handler造成内存泄露的分析和解决
- Android中使用Handler造成内存泄露的分析和解决
- Android中使用Handler造成内存泄露的分析和解决
- Android中使用Handler造成内存泄露的分析和解决
- Android使用Handler造成的内存泄露问题的解决
- Android中使用Handler造成内存泄露的分析和解决
- Android中使用Handler造成内存泄露的分析和解决
- Android中使用Handler造成内存泄露的分析和解决
- Android中使用Handler造成内存泄露的分析和解决
- 关于Android中使用Handler造成内存泄露的分析和解决
- Android中使用Handler造成内存泄露的分析和解决
- Android中使用Handler造成内存泄露的分析和解决
- Android中使用Handler造成内存泄露的分析和解决
- Android中使用Handler造成内存泄露的分析和解决
- Android中使用Handler造成内存泄露的分析和解决
- Android中使用Handler造成内存泄露的原因和解决方法
- Android中使用Handler造成内存泄露的分析和解决
- Android中使用Handler造成内存泄露的分析和解决
- Android中使用Handler造成内存泄露的分析和解决