android : inputMethodManager内存泄露
程序员文章站
2022-04-19 17:36:31
...
kotlin版本:
//override fun onDestroy() {
// CleanLeakUtils.fixInputMethodManagerLeak(this)
// super.onDestroy()
//}
object CleanLeakUtils {
fun fixInputMethodManagerLeak(destContext: Context?) {
if (destContext == null) {
return
}
val inputMethodManager = destContext.
getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
val viewArray = arrayOf("mCurRootView", "mServedView", "mNextServedView")
var filed: Field
var filedObject: Any?
for (view in viewArray) {
try {
filed = inputMethodManager.javaClass.getDeclaredField(view)
if (!filed.isAccessible) {
filed.isAccessible = true
}
filedObject = filed.get(inputMethodManager)
if (filedObject != null && filedObject is View) {
val fileView = filedObject as View?
if (fileView!!.context === destContext) {
// 被InputMethodManager持有引用的context是想要目标销毁的
filed.set(inputMethodManager, null)
// 置空,破坏掉path to gc节点
} else {
break
// 不是想要目标销毁的,即为又进了另一层界面了,
// 不要处理,避免影响原逻辑,也就不用继续for循环了
}
}
} catch (t: Throwable) {
t.printStackTrace()
}
}
}
}
Java版本:
public class CleanLeakJavaUtils {
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 (String param : arr) {
try {
f = imm.getClass().getDeclaredField(param);
if (!f.isAccessible()) {
f.setAccessible(true);
} // author: sodino mail:[email protected]
obj_get = f.get(imm);
if (obj_get instanceof View) {
View v_get = (View) obj_get;
// 被InputMethodManager持有引用的context是想要目标销毁的
if (v_get.getContext() == destContext) {
// 置空,破坏掉path to gc节点
f.set(imm, null);
} else {
// 不是想要目标销毁的,即为又进了另一层界面了,
// 不要处理,避免影响原逻辑,也就不用继续for循环了
break;
}
}
} catch (Throwable t) {
t.printStackTrace();
}
}
}
}
或
public class FixMemLeak {
private static Field field;
private static boolean hasField = true;
public static void fixLeak(Context context) {
if (!hasField) {
return;
}
InputMethodManager imm = (InputMethodManager) context.
getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm == null) {
return;
}
String[] arr = new String[]{"mLastSrvView"};
for (String param : arr) {
try {
if (field == null) {
field = imm.getClass().getDeclaredField(param);
}
if (field == null) {
hasField = false;
}
if (field != null) {
field.setAccessible(true);
field.set(imm, null);
}
} catch (Throwable t) {
t.printStackTrace();
}
}
}
}