GWT - шина событий MVP. Создание нескольких обработчиков

Я работаю в большом приложении, которое я унаследовал, и сталкиваюсь с некоторыми проблемами с лучшими практиками.

Каждый раз, когда пользователь переходит на нашу страницу редактирования клиента, создается новый докладчик и устанавливается представление. Существует основной презентатор для редактирования клиента и основной вид. В основном представлении также есть дополнительные представления, которые используются вспомогательными докладчиками основного докладчика. Внутри вспомогательных презентаторов я регистрирую обработчики событий на шине событий.

Проблема, с которой я сталкиваюсь, заключается в том, что при повторном переходе к редактору контактов ведущий создается снова, и эти события снова регистрируются. Теперь, когда происходит событие, оно обрабатывается дважды, по одному разу для каждого экземпляра докладчика.

Ведущий не удерживается переменной, но на вспомогательное представление ссылается основное представление. Может быть, эта ссылка в представлении препятствует удалению обработчиков событий? У меня сложилось впечатление, что обработчики событий будут удалены, если этот объект будет собран мусором. Если это не так, следует ли отменить регистрацию этих обработчиков событий в шине событий?

Обновление: докладчики не удаляются сборщиком мусора. Если я смогу изменить код, чтобы удалить все ссылки на этих докладчиков, когда они больше не нужны, будут ли они собираться и, следовательно, будут ли удалены обработчики событий?


person aglassman    schedule 06.12.2012    source источник


Ответы (2)


Обработчики событий — это отдельные экземпляры объектов, которые устанавливаются и сохраняются в некоторой коллекции внутри EventBus. Ваш презентатор просто создает их и передает в EventBus, поэтому на обработчики по-прежнему ссылаются за пределами жизненного цикла презентатора (и поэтому они продолжают работать). Ведущие, вероятно, не подвергаются сборке мусора, потому что обработчики все еще могут ссылаться на них или их поля.

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

Подход, который я использую, заключается в повторном использовании экземпляров View/Presenter на уровне экрана и сбросе их состояния при повторном входе. Это также помогает с производительностью. Докладчики также отслеживают экземпляры HandlerRegistration для всех обработчиков, которые они добавляют в EventBus.

Я не знал о ResettableEventBus, о котором упоминает Колин, но это тоже звучит как хорошее решение.

person filip-fku    schedule 06.12.2012
comment
Из-за того, как разработано приложение, я мог бы сделать рассматриваемого докладчика синглтоном. Таким образом, он создается только один раз. Является ли это приемлемым шаблоном проектирования для использования в GWT? - person aglassman; 07.12.2012
comment
«Приемлемо» — это объективный термин :) Вы также можете использовать GIN для создания одноэлементного экземпляра презентатора, если вы этого хотите. - person Jonathan; 07.12.2012
comment
Я попробовал шаблон singleton, и он отлично работает. Я изучу GIN и посмотрю, есть ли смысл использовать его в проекте. - person aglassman; 10.12.2012

ResettableEventBus специально разработан для этого — вместо предоставления Presenter глобальной шины событий вы оборачиваете эту шину событий в Resettable версии. Затем, когда этот презентер закрывается, тот, кто дал ему эту шину событий, сбрасывает ее, тем самым очищая все обработчики, которые он мог добавить.

Вот как управляются действия в структуре Activity/Place GWT, чтобы предотвратить их утечку.

Другой вариант — дать каждому презентеру метод типа «stop()» или «release()», указывающий, что он должен идти первым, и он должен подчищать после себя — отменить текущие вызовы RPC, удалить диалоговые окна, отменить событие. обработчики. И, как указано выше, у API-интерфейса Activity есть метод, указывающий, что он вот-вот остановится, и что он остановился и должен очиститься.

Предоставление обоих позволяет легко не делать ошибок с глобальной шиной событий, и по-прежнему дает ловушку для более мелких проблем (длительные вызовы RPC), но проблема может быть решена с помощью любого решения.

person Colin Alworth    schedule 06.12.2012
comment
ResettableEventBus звучит так, как будто это было бы полезно в моем случае. Проблема заключается в том, чтобы понять, когда выключить презентатор. К сожалению, у первоначальных разработчиков не было фреймворка Activity/Place, так что все было на заказ. Я углублюсь в код и посмотрю, смогу ли я каким-то образом определить, когда должен быть выпущен конкретный докладчик. - person aglassman; 07.12.2012
comment
Пользовательский неплох - я не использую активность / место много, но часто предпочитаю более конкретный подход. Вы правы в том, что вам нужно решить, когда докладчик закончит работу — в этом и есть суть вопроса, верно? Когда это будет сделано, заставьте его отпустить ресурсы, которые он держит. Если вы не знаете, что это не сделано, как он может знать, что пришло время выпустить эти обработчики событий? - person Colin Alworth; 07.12.2012
comment
Спасибо за вклад, но в итоге я повторно использовал один и тот же презентатор, используя шаблон singleton. Это было проще, так как мне не нужно было очищать обработчики событий. - person aglassman; 10.12.2012