InputMethodManager holds reference to the tabhost - Memory Leak - OOM Error
Asked Answered
S

3

13

View hierarchy is as follows TabActivity -> ActivityGroups -> Activities.

Using MAT I found that TabWidget is referenced by TabHost which is referenced by InputMethodManager, hence TabWidget is leaked. On Subsequent launch of application OutOfMemory Error is thrown.

Similarly all my activities are also referenced by InputMethodManager. (After closing the application all my activitygroups, activities, tabactivity, tabhost and tabwidget are leaked!!)

On Properly finishing the application (hitting back key), following is shown in logcat

WARN/InputManagerService(99): Starting input on non-focused client com.android.internal.view.IInputMethodClient$Stub$Proxy@44a87748 (uid=10052 pid=1463)

How to remove the reference from InputMethodManager...?

Thing I tried:

A. Called this method onDestroy of my TabActivity
1. myTabWidget.removeAllViews()
2. myTabWidger.invalidate()

No Luck!


Son answered 24/4, 2011 at 9:31 Comment(0)
W
1

Thing I tried: A. Called this method onDestroy of my TabActivity 1.myTabWidget.removeAllViews() 2.myTabWidger.invalidate()

Of course, it will not work. Activities aren't views neither in MVC/MVP/MVVM nor in Android SDK classes hierarchy. android.app.Activity doesn't extend android.view.View

My colleague had similar problem with memory leaks - he declared tabHost in TabActivity in static way (he wanted to access it from another activity, when he hadn't been familiar with pattern Observer). I think you've made something similar.

And, at last, my question: why do you reference activities in InputMethodManager (though I don't understand how: it's final class) and not InputMethodManager in activities? If you want global focus point for InputMethodManager, I can advice you to put reference of it to Application class. We extend Application class (for example, HostApplication), in this facade we declare common stuff (SharedPreferences, for example). And in the activities we write:

HostApplication application = (HostApplication) getApplication();

Then we get useful common stuff from it.

Waldheim answered 21/10, 2011 at 6:39 Comment(2)
I do not refer InputMethodManager anyway. Can you provide me link that explains more about "pattern Observer"?Son
en.wikipedia.org/wiki/Observer_pattern We created one model as Observable (Subject), and Activities were Observers (they implemented interface "Observer"). At start, activity registered itself in the model (we use singleton, but you can use Service or Application). If there was something interesting, observable fired event and notified every client. Before destroy, Activity unregistered itself in Observable to avoid memory leak. Most of causes for memory leak in Android are very simple: Context/View/Dialog were declared static way somewhere.Waldheim
V
3

I also met this problem and I tried some way to avoid it. When my activity is finished, I try to cut off the connection with input method manager service. Check it out:

class MyActivity extend Activity {
    @Override
    public void finish() {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.windowDismissed(mContentView.getWindowToken());
        super.finish();
    }
}

I'm not sure whether this could fix this memory leak at all. For now, it works fine. You could take a try.

View answered 14/4, 2012 at 14:30 Comment(2)
mContentView, is the reference to root view of tablayout?Son
InputMethodManager.windowDismissed is a hidden method in the Android API. So, no, it doesn't work fine. To get it working, you must use reflection: ((Class.forName("android.view.inputmethod.InputMethodManager")).getMethod("windowDismissed", IBinder.class)).invoke(null, mContentView.getWindowToken());Sagamore
W
1

Thing I tried: A. Called this method onDestroy of my TabActivity 1.myTabWidget.removeAllViews() 2.myTabWidger.invalidate()

Of course, it will not work. Activities aren't views neither in MVC/MVP/MVVM nor in Android SDK classes hierarchy. android.app.Activity doesn't extend android.view.View

My colleague had similar problem with memory leaks - he declared tabHost in TabActivity in static way (he wanted to access it from another activity, when he hadn't been familiar with pattern Observer). I think you've made something similar.

And, at last, my question: why do you reference activities in InputMethodManager (though I don't understand how: it's final class) and not InputMethodManager in activities? If you want global focus point for InputMethodManager, I can advice you to put reference of it to Application class. We extend Application class (for example, HostApplication), in this facade we declare common stuff (SharedPreferences, for example). And in the activities we write:

HostApplication application = (HostApplication) getApplication();

Then we get useful common stuff from it.

Waldheim answered 21/10, 2011 at 6:39 Comment(2)
I do not refer InputMethodManager anyway. Can you provide me link that explains more about "pattern Observer"?Son
en.wikipedia.org/wiki/Observer_pattern We created one model as Observable (Subject), and Activities were Observers (they implemented interface "Observer"). At start, activity registered itself in the model (we use singleton, but you can use Service or Application). If there was something interesting, observable fired event and notified every client. Before destroy, Activity unregistered itself in Observable to avoid memory leak. Most of causes for memory leak in Android are very simple: Context/View/Dialog were declared static way somewhere.Waldheim
C
1

Are you sure the memory leak is real? I have a similar situation, and while it looks like a memory leak in MAT, I can not get two instances of the TabActivity to appear because of the InputMethodManager. Sure, the InputMethodManager seems to keep the TabActivity from garbage collecting. But, if this was a real memory leak, wouldn't I be able to see two TabActivites, then three, then four?

(FYI, I was able to see two TabActivities at one point, but the problem wasn't the InputMethodManager, it was a static reference in the code)

Concinnity answered 30/1, 2013 at 16:9 Comment(1)
Yes you are right. InputMethoManage doesn't do anything. Problem is with a static reference I had used to switch the selected tab. In above answer by "QuickNick" has mentioned on how to remove the static reference Using obeserver pattern.Son

© 2022 - 2024 — McMap. All rights reserved.