android - Main Activity is not garbage collected after destruction because it is referenced by InputMethodManager indirectly -
i followed "avoiding memory leaks" article here.
however proposed solution not solve leak problem. tested android emulator on windows xp (sdk 2.3.1). dumped heap , checked main activity still in heap (i used mat)
here's did:
- create helloworld app helloworldactivity (it has no child views)
- run emulator , launch helloworld app.
- close clicking back-key.
- cause gc in ddms , dump heap <-- here found helloworldactivity instance.
- 'path gc roots' shows following path.
helloworldactivity <- phonewindow$decorview <- inputmethodmanager
inputmethodmanager singleton , 3 references decorview references helloworldactivity.
i can't understand why inputmethodmanager still references decorview instance after activity destroyed.
is there way make sure main activity destroyed , gc-able after closing it?
it seems calling inputmethodmanager's methods 'windowdismissed' , 'startgettingwindowfocus' stuff.
something this:
@override protected void ondestroy() { super.ondestroy(); //fix memory leak: http://code.google.com/p/android/issues/detail?id=34731 fixinputmethodmanager(); } private void fixinputmethodmanager() { final object imm = getsystemservice(context.input_method_service); final reflector.typedobject windowtoken = new reflector.typedobject(getwindow().getdecorview().getwindowtoken(), ibinder.class); reflector.invokemethodexceptionsafe(imm, "windowdismissed", windowtoken); final reflector.typedobject view = new reflector.typedobject(null, view.class); reflector.invokemethodexceptionsafe(imm, "startgettingwindowfocus", view); }
reflector's code:
public static final class typedobject { private final object object; private final class type; public typedobject(final object object, final class type) { this.object = object; this.type = type; } object getobject() { return object; } class gettype() { return type; } } public static void invokemethodexceptionsafe(final object methodowner, final string method, final typedobject... arguments) { if (null == methodowner) { return; } try { final class<?>[] types = null == arguments ? new class[0] : new class[arguments.length]; final object[] objects = null == arguments ? new object[0] : new object[arguments.length]; if (null != arguments) { (int = 0, limit = types.length; < limit; i++) { types[i] = arguments[i].gettype(); objects[i] = arguments[i].getobject(); } } final method declaredmethod = methodowner.getclass().getdeclaredmethod(method, types); declaredmethod.setaccessible(true); declaredmethod.invoke(methodowner, objects); } catch (final throwable ignored) { } }
Comments
Post a Comment