Код разделён на пакеты client
, shared
, server
и lib
: первые три пакета содержат только код, относящийся к примеру, а последний пакет — код самой библиотеки.
Все события, которые используются в этом коде происходят за счёт передачи дочерними шинами событий (ChildEventBus), через форвардинг, сигналов в главную шину событий (IsMainEventBus). Все такие события перечислены в интерфейсе IsMainEventBus. Из главной шины событий они передаются в презентер основной страницы (AMainPresenter) и там обрабатываются надлежащим образом.
В mvp4g-HistoryConverter модуля новое событие приходит в виде строки события и строки параметров (поэтому все навигационные события в приложении должны проходить через историю, это достигается через настройку шин событий). По двум этим строкам, воспользовавшись списком зарегистрированных страниц, описывающим связь страниц с событиями и лэйаутами, мы можем получить соответственно страницу, текущий URL и идентификатор лэйаута. Это происходит в методе convertFromToken
класса PortalsHistoryConverter.
PortalsHistoryConverter, перед вызовом навигационного события, подготавливает экземпляр класса CanBuildLayout, который может лениво (по запросу) построить лэйаут и заполнить его виджетами, используя LayoutBuilder текущего модуля. Этот экземпляр передаётся в событие newPortal(...)
, которое уходит в презентер главной страницы и он принимает решение о необходимости построения нового лэйаута (если изменился лэйаут или изменилось состояние) и, если решение положительное, запрашивает фактическое построение лэйаута (создание экземпляра) и заполнение его виджетами по текущему состоянию через LayoutBuilder.
LayoutBuilder передаёт в абстрактный метод layout
для дочернего класса текуший портал, состояние страницы (null
, если его нет) и идентификатор лэйаута. По ним дочерний класс может однозначно определить, какими виджетами и в каком состоянии нужно заполнить плэйсходеры лэйаута через событие plug
шины событий любого дочернего модуля. Событие plug
передаётся в главный презентер и тот подключает “вилки” в “розетки” текущего лэйаута.
После этого класс PortalsHistoryConverter вызывает абстрактный метод covertFromUrl
и передаёт в него полученный URL и идентификатор портала. По этому идентификатору портала дочерний конвертер может вызвать надлежащее навигационное событие.
Таким образом, сначала строится лэйаут страницы, а затем — вызывется навигационное событие. После выполнения навигационного пользователь может запрашивать изменение состояния через событие updateState(Place, State)
для обновления состояния всей страницы (когда place
== null
) или её части. Это событие также обрабатывается главным презентером, который при необходимости либо обновляет лэйаут через LayoutBuilder
, либо просто подменяет нужную “розетку”.
По сути, это весь механизм, остальное — тонкости, которые, надеюсь, будут понятны из кода.
P.S. На данный момент в коде не используются ни аннотации, ни Dependency Injection, хотя возможно, надо бы.