InputMethodManager содержит ссылку на tabhost — утечка памяти — ошибка OOM

Иерархия представлений следующая: TabActivity -> ActivityGroups -> Activities.

Используя MAT, я обнаружил, что на TabWidget ссылается TabHost, на который ссылается InputMethodManager, поэтому TabWidget просочился. При последующем запуске приложения выдается ошибка OutOfMemory.

Точно так же все мои действия также упоминаются InputMethodManager. (После закрытия приложения все мои группы действий, действия, активность вкладок, вкладки и виджеты вкладок просочились!!)

При правильном завершении приложения (нажатие клавиши возврата) в logcat показано следующее

WARN/InputManagerService(99): запуск ввода на клиенте без фокусировки com.android.internal.view.IInputMethodClient$Stub$Proxy@44a87748 (uid=10052 pid=1463)

Как удалить ссылку из InputMethodManager...?

Что я пробовал:

A. Назвал этот метод onDestroy моего TabActivity
1. myTabWidget.removeAllViews()
2. myTabWidger.invalidate()

Не повезло!



person Mani    schedule 24.04.2011    source источник


Ответы (3)


Что я пробовал: A. Вызвал этот метод onDestroy моей TabActivity 1.myTabWidget.removeAllViews() 2.myTabWidger.invalidate()

Конечно, это не сработает. Действия не являются представлениями ни в MVC/MVP/MVVM, ни в иерархии классов Android SDK. android.app.Activity не расширяет android.view.View

У моего коллеги была аналогичная проблема с утечками памяти - он объявил tabHost в TabActivity статическим способом (он хотел получить к нему доступ из другого действия, когда он не был знаком с паттерном Observer). Я думаю, что вы сделали что-то подобное.

И, наконец, мой вопрос: почему вы ссылаетесь на действия в InputMethodManager (правда, я не понимаю как: это конечный класс), а не на InputMethodManager в действиях? Если вам нужна глобальная точка фокусировки для InputMethodManager, я могу посоветовать вам поместить ссылку на нее в класс Application. Мы расширяем класс Application (например, HostApplication), в этом фасаде мы объявляем общие вещи (например, SharedPreferences). А в активностях пишем:

HostApplication application = (HostApplication) getApplication();

Затем мы получаем полезные общие вещи из него.

person QuickNick    schedule 21.10.2011
comment
Я все равно не ссылаюсь на InputMethodManager. Можете ли вы предоставить мне ссылку, которая больше объясняет о Pattern Observer? - person Mani; 24.10.2011
comment
en.wikipedia.org/wiki/Observer_pattern Мы создали одну модель как Observable (Subject) и Действия были наблюдателями (они реализовали интерфейс Observer). При старте активность зарегистрировалась в модели (мы используем singleton, но можно использовать Service или Application). Если происходило что-то интересное, наблюдаемое событие запускалось и уведомлялось об этом каждому клиенту. Перед уничтожением Activity отменила регистрацию в Observable, чтобы избежать утечки памяти. Большинство причин утечки памяти в Android очень просты: Context/View/Dialog были где-то объявлены статически. - person QuickNick; 25.10.2011

Я также столкнулся с этой проблемой, и я попытался каким-то образом избежать ее. Когда моя деятельность завершена, я пытаюсь отключить соединение со службой диспетчера методов ввода. Проверьте это:

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

Я не уверен, может ли это вообще исправить эту утечку памяти. На данный момент это работает нормально. Вы могли бы попробовать.

person A.TNG    schedule 14.04.2012
comment
mContentView, это ссылка на корневой вид tablayout? - person Mani; 17.04.2012
comment
InputMethodManager.windowDismissed — это скрытый метод в Android API. Так что нет, это не работает нормально. Чтобы заставить его работать, вы должны использовать отражение: ((Class.forName("android.view.inputmethod.InputMethodManager")).getMethod("windowDismissed", IBinder.class)).invoke(null, mContentView.getWindowToken()); - person iamreptar; 06.03.2014

Вы уверены, что утечка памяти реальна? У меня похожая ситуация, и хотя это выглядит как утечка памяти в MAT, я не могу получить два экземпляра TabActivity из-за InputMethodManager. Конечно, InputMethodManager, похоже, не позволяет TabActivity собирать мусор. Но если бы это была настоящая утечка памяти, разве я не смог бы увидеть две TabActivites, затем три, затем четыре?

(К вашему сведению, в какой-то момент я смог увидеть две TabActivities, но проблема была не в InputMethodManager, а в статической ссылке в коде)

person Justin    schedule 30.01.2013
comment
Да, ты прав. InputMethoManage ничего не делает. Проблема в статической ссылке, которую я использовал для переключения выбранной вкладки. В приведенном выше ответе QuickNick упомянул, как удалить статическую ссылку с помощью шаблона наблюдателя. - person Mani; 01.02.2013