Flex Pure MVC архитектура для приложений enterprise уровня  Sergiy Shychynov (EPAM)   2012-03-24
Содержание1.        Сначала мы вспомним основные составляющие          микроахитектуры PureMVC.2.        Далее рассмотрим ...
Основные составляющие PureMVCиспользуя презентацию Samuel Asher Rivello)http://www.adobe.com/newsletters/inspire/december2...
Схема взаимодействия компонентов PureMVCдля выполнения элементарной операции   Внешний вид компонента Hello Google –    к...
Основные задачи, возникающие прииспользовании PureMVC в больших проектах.«Приложение enterprise уровня» - БОЛЬШИЕБОЛЬШОЕ к...
Форма - Списки контактов и контактных групп
Форма – менеджер валют
Форма – редактирование контакта
Форма - Аудит
Форма – Редактирование конвейера операциймаппинг процессора для бла-бла-бла
Форма – Маппинг полей метода сервисапередачи телефонных сообщений.
3 вида компонентов
Среди всего UI большого приложения можновыделить элементы (подсистемы)1.   постоянно находятся на экране и доступны для вз...
Жизненный цикл элементов системы иосновные операции над ними.1.        создать и разместить в иерархии DisplayObjects необ...
Необходимость синхронизации работы медиаторов сасинхронно создаваемыми видимыми элементами.   Как известно видимые элемен...
DefferedMediator   constructor() – чистый конструктор   create(); - все что хотелось сделать в конструкторе   initializ...
Кто, когда и как создает видимые элементы.Медиатор знает класс своего(-их) компонентов.Медиатор знает где должен быть его ...
Пример взаимодействия слот-холдера и егоклиентов
«Страничная» PureMVC архитектура«Страница» – это некоторое множество компонентов,функционирующих совместно в одном промежу...
Основные задачи                                PagesProxy     хранение справочника всех страниц системы    function getPag...
PageDescription   pageName:String,   preloader:Class,        - клоасс-наследник BasePagePreloader   mediators:Array,   ...
Вызов ViewPageCommandРегистрация командыfacade.registerCommand(BaseNotifications.VIEW_PAGE, ViewPageCommand);Вызов команды...
Пример дескриптора страницыnew PageDescription( Pages.QUESTIONNAIRE,    QuestionnaireAnswerPreloader,    [QuestionnaireSlo...
pageDescriptor – ищем по имени страницы            Проверяет наличие дескриптора страницы                stateParams : {} ...
Прелоадер – PreloaderПрелоадер загружает несколько «частей» данных (прокси илиделегаты).После полной загрузки всех частей ...
BasePreloaderMediator   var stateParams:Object;   var viewParams:PageNotificationParams;Override it to create more prelo...
Пример прелоадера «детям до 16»   public class ManageGroupMembershipPreloader extends BasePreloaderMediator   {       o...
МодульностьВ настоящее время система имеет:   полторы сотни (150) основных страниц со связанными с ними rollover    форма...
Соображения по поводу Модульности Необходимо: при начальной загрузке загружать только ядро системы, а все дополнительные, ...
Структура иерархии модулей   Module – единица компиляции и линковки   ModuleDescription – содержит полный набор всех Pag...
public function ModuleMain(){    super();    _moduleDescription = new ModuleDescriptionMain();    //NameUtils.registerServ...
public class PageDescriptionsResourcesAssets{public static const commonBreadcrumbs:Array = [Pages.R_A_VIEW_ROOT_RESOURCES]...
moduleDescriptors.xml   <?xml version="1.0" encoding="UTF-8"?>   <Modules>     <Module name="ModuleMain">       <Pages...
Проблема регистрации классов дляримотинга.[RemoteClass(alias="com.os.sp.domain.messaging.MessagesGroup")]public class Mess...
Фрагмент ant-task-а компиляции основногоприложения (ядра системы)   <property name="FLEX_INCLUDE_VO_CONFIGURATION" value=...
КОНЕЦSergiy_Shychynov@epam.com
НО
ОСТАЛОСЬ НЕ ОХВАЧЕННЫМВзаимодействие View Components и Mediators    Шаблон «страницы»    Интерфейс «страничного» View Co...
А ТАКЖЕ    Базовые классы медиаторов        Медиатор формы        Медиатор листа        Медиатор попапа    Подсистема...
Приложение: особенности реализацииSlotHolder медиаторов   Задача по созданию и связыванию вью компонентов с    медиаторам...
Способы создания и связывани компонента смедиатором.   protected function setupMediator(…)       mediatorName:String = n...
Особенности реализации протокола взаимодействияслот-холдер медиаторов с их клиентами.   override public function listNoti...
   private function defaultSlotHolderNotificationHandler(notification:INotification):void   {       if(slots && slots[n...
Интересный АнтипаттернДалее описан антипаттерн, который используется для оптимизации взаимодействия слотхолдеров. Номне не...
Пример использования:   * Try to add view component in appropriate external slot. If there isnt   * appropriate slot the...
Enterprise flex pure mvc, slides, russian
Enterprise flex pure mvc, slides, russian
Enterprise flex pure mvc, slides, russian
Enterprise flex pure mvc, slides, russian
Enterprise flex pure mvc, slides, russian
Upcoming SlideShare
Loading in …5
×

Enterprise flex pure mvc, slides, russian

1,007 views
898 views

Published on

Flex Pure MVC архитектура для приложений enterprise уровня. Доклад для UA FPUG - встреча 35.

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,007
On SlideShare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
3
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Enterprise flex pure mvc, slides, russian

  1. 1. Flex Pure MVC архитектура для приложений enterprise уровня Sergiy Shychynov (EPAM) 2012-03-24
  2. 2. Содержание1. Сначала мы вспомним основные составляющие микроахитектуры PureMVC.2. Далее рассмотрим структуру и задачи, возникающие при использовании PureMVC в больших проектах. 1. Разновидности и жизненный цикл элементов системы 2. Необходимость синхронизации работы медиаторов с асинхронно создаваемыми видимыми элементами.3. «Страничная» архитектура для PureMVC проекта: 1. Управление View компонентами в «страничной» архитектуре: 1. Отложенное (deferred) создание, 2. Расположение в иерархии Display Objects. 2. Жизненный цикл «страницы», дескриптор «страницы» 3. Прелоадер страницы4. Использование модулей в «страничной» архитектуре.
  3. 3. Основные составляющие PureMVCиспользуя презентацию Samuel Asher Rivello)http://www.adobe.com/newsletters/inspire/december2008/articles/article6/index.htmlMVC in PureMVC
  4. 4. Схема взаимодействия компонентов PureMVCдля выполнения элементарной операции Внешний вид компонента Hello Google – кнопка и текстовое поле для сообщения Последовательность элементарных действий выполняемых при нажатии кнопки Положение этих действий на диаграмме PureMVC
  5. 5. Основные задачи, возникающие прииспользовании PureMVC в больших проектах.«Приложение enterprise уровня» - БОЛЬШИЕБОЛЬШОЕ количество РАЗНЫХ форм и компонентов,которые необходимо будет использовать в разныхситуациях и в разное времяРечи о том, что все элементы будут созданыодновременно или заранее быть не может. Более того –было бы неплохо, чтобы и грузить их все сразу нетребовалось.Рассмотрим несколько разных «видов» гипотетическогобольшого приложения.
  6. 6. Форма - Списки контактов и контактных групп
  7. 7. Форма – менеджер валют
  8. 8. Форма – редактирование контакта
  9. 9. Форма - Аудит
  10. 10. Форма – Редактирование конвейера операциймаппинг процессора для бла-бла-бла
  11. 11. Форма – Маппинг полей метода сервисапередачи телефонных сообщений.
  12. 12. 3 вида компонентов
  13. 13. Среди всего UI большого приложения можновыделить элементы (подсистемы)1. постоянно находятся на экране и доступны для взаимодействия.2. могут вызываться пользователем на экран по желанию и ведут себя относительно независимо от других элементов UI.3. которые имеют отношение к текущей операции, выполняемой пользователем, показываются на экране когда он начинает выполнять эту операцию и будут убраны с экрана когда он эту операцию завершит. Причем таких циклов появления и исчезновения с экрана может быть много. Этот третий тип подсистем мы будем в дальнейшем называть страницами – Pages.И если операции по обслуживанию жизненного цикла для 1 и 2 типа можновыполнить один раз (например в StartupCommand), то выполнение всехнижеперечисленных действий для компонентов подсистем 3-его типаявляется рутинной операцией и нуждается в автоматизации.
  14. 14. Жизненный цикл элементов системы иосновные операции над ними.1. создать и разместить в иерархии DisplayObjects необходимые компоненты - ViewComponents.2. создать и зарегистрировать необходимые медиаторы – Mediators.3. связать медиаторы с соответствующими компонентами ссылки на компоненты, прослушивание события от компонентов4. зарегистрировать необходимые для работы подсистемы команды – Commands5. создать и зарегистрировать необходимые для работы прокси – Proxy,6. отобразить в компонентах валидные данные 1. загружаются с сервера - определенное время 2. загружаются с сервера – «ошибки технические» 3. политики безопасности – запрещено смотреть данные – «ошибки логические» 4. Не стоит показывать на экране новые компоненты, еще не заполненные данными, до того как эти данные будут получены с сервера. 5. Это процесс мы будем называть предзагрузка – preloader.7. основной цикл работы – стандартный 1. Отдельный вопрос – это обработка ошибок (серверных). Бывают устранимые и неустранимые ошибки – остаемся на странице, обновляем или покидаем ее.8. после завершения операции - корректно освободить ресурсы системы от текущей «страницы» 1. Отписывание медиаторов от событий, которые они прослушивали от компонентов. 2. Удаление «актеров» PureMVC (медиаторов) 1. «отписать» медиаторы от системы (unregister) 2. удалять медиаторы или сохранять их в «кэше» 3. команды тоже можно «отписать» от системы, 4. прокси отписывать от системы и удалять – как правило не нужно и даже вредно. 3. Удаление видимых компонентов - операция создания компонента и добавления его в DisplayList более ресурсоемкая, чем сделать невидимый компонент – видимым. НЕ удалять а делать невидимыми 4. Очистить ссылки на временные данные - Garbage Collector освободит память.
  15. 15. Необходимость синхронизации работы медиаторов сасинхронно создаваемыми видимыми элементами. Как известно видимые элементы – компоненты флекса не создаются мгновенно по запросу. Как правил от момента создание экземпляра компонента, установки его свойств и добавления его в иерархию DisplayObjects проходит некоторое время и несколько этапов, прежде чем событие «creationComplete» дает нам знать, что компонент и все его подкомпоненты полностью созданы и готовы к работе. До этого момента медиатор, даже если и будет иметь ссылку на компонент, не сможет полноценно с ним работать. DefferedMediator - решает проблему асинхронного создания компонентов. Откладывает вызовы initialize и activate до момента, когда компонент будет создан и инициализирован. А потом еще откладывает update до момента, когда все медиаторы из списка будут активированы.
  16. 16. DefferedMediator constructor() – чистый конструктор create(); - все что хотелось сделать в конструкторе initialize(); - в том числе addViewListeners уровня инициализации activate(); - в том числе addViewListeners уровня активацииwaitForMediatorsActivation(mediatorNames); update(); - основной цикл deactivate(); – в том числе автоматически удаляет eventListeners уровня активации finalize(); – в том числе автоматически удаляет eventListeners уровня инициализации
  17. 17. Кто, когда и как создает видимые элементы.Медиатор знает класс своего(-их) компонентов.Медиатор знает где должен быть его компонент. SlotViewComponentDescription viewComponentName = "M1“ viewComponentSlot = "SlotAMediator" viewComponent = UIComponent Медиатор-слотхолдер Медиатор-клиент “SlotAMediator” получает M1Mediator создает нотификейшен, адресованный компонент и отправляет его ему и добавляет в свой слот новый компонент под именем слоту "SlotAMediator" - "M1“. просит его хранить под именем "M1“. Обычно в методе create() Слот – это обычно ViewStack или другой контейнер.
  18. 18. Пример взаимодействия слот-холдера и егоклиентов
  19. 19. «Страничная» PureMVC архитектура«Страница» – это некоторое множество компонентов,функционирующих совместно в одном промежуткевремени.Эти компоненты и обслуживающие их актеры PureMVCсовместно создаются, работают и удаляются.Чтобы не писать отдельные команды для открытиякаждой страницы, была создана единая командаоткрытия новой страницы ViewPageCommand, котораяиспользует PageDescription страницы и работаетсовместно с Pages Proxy.
  20. 20. Основные задачи PagesProxy хранение справочника всех страниц системы function getPageDescription(pageName:String):PageDescription хранение информации о текущей открытой странице (ее имя, дескриптор, стейт, состояние редактирование, helpContext и прочее)Соответственно все страницы имеют уникальные именаpublic class Pages{ public static const ABOUT:String = "about"; public static const ADMIN_EMAIL_TEMPLATE_EDIT:String = "adminEmailTemplateEdit"; public static const DOCUMENT_TRANSLATION:String = "documentTranslation";…}и дескрипторы
  21. 21. PageDescription pageName:String, preloader:Class, - клоасс-наследник BasePagePreloader mediators:Array, - список классов-наследников BaseMediator proxies:Array = null, - список классов-наследников BaseProxy commands:Array = null, - список CommandDescription(name:String, commandClass:Class) stateParams:Object = null, - редко встречающиеся доп. параметры pageTitle:String = null, } - часто встречающиеся доп. параметры breadcrumbs:Array = null. … }
  22. 22. Вызов ViewPageCommandРегистрация командыfacade.registerCommand(BaseNotifications.VIEW_PAGE, ViewPageCommand);Вызов команды активации страницыvar params:PageNotificationParams = new PageNotificationParams();params.pageName = Pages.IMPORT_REPORT;params.id = importReport.id;params.documentType = importReport.dataType;sendNotification(BaseNotifications.VIEW_PAGE, params);PageNotificationParams var pageName:String; var pageState:String; var id:Number; var backPageName:String; var preloader:BasePreloaderMediator; - создается и добавляется в процессе открытия
  23. 23. Пример дескриптора страницыnew PageDescription( Pages.QUESTIONNAIRE, QuestionnaireAnswerPreloader, [QuestionnaireSlotHolderMediator, QuestionnaireAnswerMediator], [QuestionnairesProxy, ProcessEditProxy, ProcessTypesListProxy, TimeScaleProxy], [ new CommandDescription(SPNotification.FIND_NEW_QUEST, LoadQuestiannairCommand), new CommandDescription(SPNotification.UPDATE_ASSET_QUEST, UpdateAssetCommand), ], { questionnaireComponentState: QuestionnaireComponentState.ANSWER }, "Questionnaire Registry")Далее описание алгоритма работы ViewPageCommand …
  24. 24. pageDescriptor – ищем по имени страницы Проверяет наличие дескриптора страницы stateParams : {} – доп. набором параметров страницы не вошедшие в дескриптор (редко) (если надо грузит нужный модуль) viewParams : PageNotificationParams – параметры страницы, заполняемые при ее открытии (все которые нужны часто) Создает и регистрирует необходимые прокси validate() & Создает и запускает прелоадер load() препроцессинг -- отписывает от системы медиаторы - подчищает «временные» данные + - отписывает медиатор от events Закрывает текущую страницукомпонентов Страница не - добавляет прелоадер во viewParams открывается Регистрирует команды Если создаются, то в следующем порядке: - Конструктор Создает (или достает из кеша) медиаторы - Setup params (stateParams и viewParams) - create() Медиаторы должны создать свои компоненты, Активирует медиаторы. разместить их в иерархии DisplayLists, сделать видимыми и подписаться на необходимые events. После активации всех вызывается update()
  25. 25. Прелоадер – PreloaderПрелоадер загружает несколько «частей» данных (прокси илиделегаты).После полной загрузки всех частей возможна их валидация идополнительная обработка.Если валидатор выдает false, страница не будет открыта - вместо этогобудет выведено сообщение об ошибке.Фрагмент кода вызова прелоадера при открытии страницыif(pageDesc.preloader != null){ setLoadingState(true); registerProxies(); // for preloading var preloaderMediator:BasePreloaderMediator = new (pageDesc.preloader)(); preloaderMediator.viewParams = params; preloaderMediator.stateParams = pageDescriptor.stateParam; preloaderMediator.callback = executeAfterPreload; preloaderMediator.load();
  26. 26. BasePreloaderMediator var stateParams:Object; var viewParams:PageNotificationParams;Override it to create more preloader parts. You can use viewParams and stateParams. function load():void { addDelegatePreloaderPart("YYYid", ResourceTypeDelegate.instance.getResourceTypeById(id)); //... addNotificationPreloaderPart("XXXid", XXXResultNotification, XXXFaultNotification); xxxProxy.load(blablabla); //... activate(); }Override it to validate loaded data. If ERROR - set preloader.errorKey before returning false value. function validate():Boolean { if(preloader.errorKey == null) { // достаем нужное нам данное и проверяем getPart("YYYid") – используем для проверки } return (preloader.errorKey == null); }
  27. 27. Пример прелоадера «детям до 16» public class ManageGroupMembershipPreloader extends BasePreloaderMediator { override public function load():void {  if(!isNaN(id)) addDelegatePreloaderPart(ContactProxy.CONTACT, ContactDelegate.instance.getContactById(id) ); addNotificationPreloaderPart(LanguageProxy.PLAIN_LANGUAGE_LIST, SPNotification.PLAIN_LANGUAGE_LIST_LOADED, SPNotification.PLAIN_LANGUAGE_LIST_FAILED); LanguageProxy(facade.retrieveProxy(LanguageProxy.NAME)).getPlainLanguageList(); super.load(); } override public function validate():Boolean { if(super.validate()) { var contact:Contact = getPart(ContactProxy.CONTACT) as Contact; if(contact != null && contact.age < 16) setPreloaderError("Просмотр этой страницы не разрешен детям до 16"); return super.validate(); } }
  28. 28. МодульностьВ настоящее время система имеет: полторы сотни (150) основных страниц со связанными с ними rollover формами, несколько десятков popup-форм некоторое кол-во подсистем,  работающих постоянно на экране,  вызываемых по требованию пользователя  или работающий в качестве «демонов» – daemon (ping, system messages)  и «сервисов» (messages, multiple operations, progress indication etc.)Кодовая база клиентской части проекта включает более 2000 файлов. Из нихболее 1600 as файлов и около 400 mxml.При этом с точки зрения заказчика это все разбито на 8 логических «модулей»и лицензия на использование каждого из них может покупаться отдельно.Кроме того многие пользователи могут не иметь доступа к некоторым модулям(администрирование, отчеты) по соображениям безопасности или в соответствиис их ролями в системе.
  29. 29. Соображения по поводу Модульности Необходимо: при начальной загрузке загружать только ядро системы, а все дополнительные, не всегда или редко используемые возможности подгружать по требованию. Для уменьшения времени загрузки и потребляемого трафика.  RSL для этого использовать нельзя:  приходилось бы вручную выбирать какие классы включать в эту библиотеку а какие - нет  Флексовые модули для этого как бы не задумывались, но воспользоваться ими получилось:  линкер mxmlc при компиляции модуля позволяет собрать все классы, по цепочке зависимостей,  есть возможность указать линкеру, что необходимо исключить классы, которые уже есть в ядре приложения.  «Страничная» организация – основа сборки модуля.  PageDescriptor – это узел для дерева линковки всех классов  модуль подгружает ViewPageCommand в момент когда впервые понадобиться страница содержащаяся в этом модуле  узнает из справочника в каком модуле находится нужная страница (moduleDescriptors.xml )  после загрузки модуля, все PageDescriptors из модуля добавляются в PagesProxy
  30. 30. Структура иерархии модулей Module – единица компиляции и линковки ModuleDescription – содержит полный набор всех Page Descriptors модуля PageDescriptionsXXX – логически сгруппированные наборы дескрипторов страницmoduleDescriptors.xml – справочник, содержащийинформацию о том какая страница в каком модуле содержитсяflex-include-vo.xml – список всех VO системы для включения вядро системы (решение проблемы регистрации VO дляремотинга)Соответствующие ANT скрипты.!!! НИКОГДА не включайте модули из среды Flash Builder!!!
  31. 31. public function ModuleMain(){ super(); _moduleDescription = new ModuleDescriptionMain(); //NameUtils.registerServerClass(ContactTask); initializeModule();}public function ModuleDescriptionMain(){ super("ModuleMain", [], [] .concat(PageDescriptionsMain.pageDescriptions) .concat(PageDescriptionsContacts.pageDescriptions) .concat(PageDescriptionsReporting.pageDescriptions) );}
  32. 32. public class PageDescriptionsResourcesAssets{public static const commonBreadcrumbs:Array = [Pages.R_A_VIEW_ROOT_RESOURCES];public static const commonProxies:Array = [ResourceTypeProxy, ParentListProxy, SessionDataProxy,AssetProxy, ProcessEditProxy, ProcessesListProxy ];public static const pageDescriptions:Array = [/////////////////////////////////////////////new PageDescription(Pages.UPDATE_RESOURCE_TYPE, PageState.ADD_EDIT_VIEW, ResourceTypeEditPreloader, Pages.R_A_VIEW_ROOT_RESOURCES, [ResourcesSlotHolderMediator, ResourceTypeEditMediator], [SessionDataProxy, AssetProxy, ProcessEditProxy], [ new CommandDescription(SPNotification.FIND_ASSET_FOR_DETAILS, LoadAssetCommand), new CommandDescription(SPNotification.FIND_ASSET_FOR_EDIT, LoadAssetEditCommand), ], {accessArea: AccessArea.RESOURCE_TYPES}, commonBreadcrumbs.concat(), "page.updateResourceType.title", "page.updateResourceType.breadcrumbLabel", null).addAddPageState(null, "page.createResourceType.title", "page.createResourceType.breadcrumbLabel").addViewPageState(null, "page.updateResourceType.viewTitle", "page.updateResourceType.viewBreadcrumbLabel").addLibraryPageState( Pages.R_A_UPDATE_RESOURCE_TYPE_FOR_LIBRARY),new PageDescription(Pages.QUESTIONNAIRE, PageState.EDIT_VIEW, QuestionnaireAnswerPreloader, null, [QuestionnaireAnswerMediator], [QuestionnairesProxy, ProcessEditProxy, ProcessTypesListProxy], null, {questionnaireComponentState:QuestionnaireComponentState.ANSWER}, [TreeNodeBase.NODE_BIA]).registerRollover(Rollovers.QUESTIANNAIRE_RECOVERY_SCHEDULE, PageState.ADD_EDIT_VIEW).registerRollover(Rollovers.QUESTIONNAIRE_ADD_PROCESS, PageState.ADD_EDIT_VIEW)] /////////////////////////////////////////////}
  33. 33. moduleDescriptors.xml <?xml version="1.0" encoding="UTF-8"?> <Modules> <Module name="ModuleMain"> <Pages> <Page name="about"/> <Page name="myTasksPage"/> </Pages> <Dependencies/> </Module> <Module name="ModuleAdministration"> <Pages> <Page name="adminLogo"/> <Page name="adminLanguageEditor"/> <Page name="auditTrail"/> </Pages> <Dependencies/> </Module> </Modules>
  34. 34. Проблема регистрации классов дляримотинга.[RemoteClass(alias="com.os.sp.domain.messaging.MessagesGroup")]public class MessagesGroup extends MessagesGroupBase implements IOSSPMessage {}!!! Не регистрирует класс, если VO линкуется через модуль!Решение проблемы:1) в модуле делаем registerClassAlias(getClassServerName(classRef), classRef);2) линкуем все VO в ядро системы (flex-include-vo.xml) <?xml version="1.0"?> <flex-config> <includes append="true"> <symbol>com.os.sp.domain.messaging.MessagesGroup</symbol> <symbol>com.os.sp.domain.messaging.SmsCostConfig</symbol> <symbol>com.os.sp.domain.integrity.InvalidRecord</symbol> </includes> </flex-config>
  35. 35. Фрагмент ant-task-а компиляции основногоприложения (ядра системы) <property name="FLEX_INCLUDE_VO_CONFIGURATION" value="${MAIN_SOURCE_FOLDER}/flex-include-vo.xml" /> <mxmlc file="${MAIN_SOURCE_FOLDER}/${ROOT_APPLICATION}.mxml" output="@{output}.swf" link-report="${BUILD_FOLDER}/${ROOT_APPLICATION}.${FULL_LINK_REPORT_POSTFIX}" > <load-config filename="${FLEX_LOCAL_CONFIGURATION}"/> </mxmlc> Компиляция модулей <target name="compile-modules" if="flex.modular.exist"> <compile-module-simple moduleName="ModuleAdministration" /> <compile-module-simple moduleName="ModuleMessaging" /> <compile-module-simple moduleName="ModuleImportExport" /> </target> Фрагмент из макроопределения компиляции модуля <mxmlc file="${MODULE_SOURCE_FOLDER}/@{moduleName}.@{moduleType}" output="${BUILD_FOLDER}/@{moduleName}.swf" load-externs="${BUILD_FOLDER}/@{dependsOn}.${FULL_LINK_REPORT_POSTFIX}" > </mxmlc>
  36. 36. КОНЕЦSergiy_Shychynov@epam.com
  37. 37. НО
  38. 38. ОСТАЛОСЬ НЕ ОХВАЧЕННЫМВзаимодействие View Components и Mediators  Шаблон «страницы»  Интерфейс «страничного» View Component  Обмен данными между медиатором и View компонентом.  Состояние «редактирования» (Editing state)  Обработка нажатий кнопок (Buttons)  Обработка других команд (пример – Chevrons) …
  39. 39. А ТАКЖЕ  Базовые классы медиаторов  Медиатор формы  Медиатор листа  Медиатор попапа  Подсистема Proxy-Delegate-Preloader  Локализация приложений …
  40. 40. Приложение: особенности реализацииSlotHolder медиаторов Задача по созданию и связыванию вью компонентов с медиаторами возложена на медиатор. Медиатору известен класс его компонента. При создании медиатора – в методе create() – медиатор создает инстанс класса вью компонента и отправляет его слот-холдер медиатору чтобы тот поместил его себе в DisplayList.
  41. 41. Способы создания и связывани компонента смедиатором. protected function setupMediator(…) mediatorName:String = null, // AUTO – такое же как имя класса – для регистрации в PureMVC viewComponentReference:Object = null, // 1) null must be null, // 2) component class // 3) component instance (descendant of UIComponent) viewComponentName:String = null, // viewComponent custom name // AUTO – по имени медиатора без постфикса Mediator // будет использовано как id и name в слотхолдере viewComponentSlot:String = null, // specific slot for register/find viewComponent (if need) viewComponentInitAction:int = 0 // special init action (0 - no action)  INIT_NONE:int = 0; // no action  INIT_FIND_OR_WAITING_FOR_THE_VIEW_COMPONENT:int = 1;  // find view component with appropriate name in appropriate slot or (in not found)  // listen for the BaseNotifications.SLOT_VIEW_COMPONENT_CREATION_COMPLETE notification  INIT_FIND_VIEW_COMPONENT:int = 2;  // find view component with appropriate name in appropriate slot  INIT_ADD_TO_SLOT:int = 4;  // add view component to appropriate slot using appropriate name
  42. 42. Особенности реализации протокола взаимодействияслот-холдер медиаторов с их клиентами. override public function listNotificationInterests():Array { return (slots == null) ? super.listNotificationInterests() : super.listNotificationInterests().concat( BaseNotifications.SLOT_VIEW_COMPONENT_ADD, BaseNotifications.SLOT_VIEW_COMPONENT_REMOVE_BY_NAME, BaseNotifications.SLOT_VIEW_COMPONENT_SHOW, BaseNotifications.SLOT_VIEW_COMPONENT_HIDE, BaseNotifications.SLOT_VIEW_COMPONENT_FIND ); } override public function handleNotification(notification:INotification):void { super.handleNotification(notification); … }
  43. 43.  private function defaultSlotHolderNotificationHandler(notification:INotification):void { if(slots && slots[notification.getType()]) { var desc:SlotViewComponentDescription = notification.getBody() as SVCD; var component:UIComponent; component = getViewComponentFromSlot(desc.viewComponentSlot, desc.viewComponentName); switch(notification.getName()) { case BaseNotifications.SLOT_VIEW_COMPONENT_SHOW: FlexUIComponentsUtils.showViewComponent(component, true); break; case BaseNotifications.SLOT_VIEW_COMPONENT_HIDE: component.visible = false; break; case BaseNotifications.SLOT_VIEW_COMPONENT_ADD: addViewComponentToInternalSlot(desc); desc.viewComponent = null; // mark viewComponent as added break; case BaseNotifications.SLOT_VIEW_COMPONENT_REMOVE_BY_NAME: removeViewComponentFromSlotByName(desc); break; case BaseNotifications.SLOT_VIEW_COMPONENT_FIND: desc.viewComponent = component; break; }}}
  44. 44. Интересный АнтипаттернДалее описан антипаттерн, который используется для оптимизации взаимодействия слотхолдеров. Номне не стыдно, потому что это, с одной стороны – служит оптимизации (можно было и не делать), сдругой – можно было бы без этого обойтись просто воспользовавшись синглтоном-менеджером. * Register handler for Notification - works just like addEventListebner. * It doesnt depend on registerMediator/removeMediator !BE AWARE! function addNotificationListener(notificationName:String, handler:Function):void { org.puremvc.as3.core.View.getInstance().registerObserver(notificationName, new Observer(handler, this) ); } * Remove Notification handler - works just like removeEventListebner. * It doesnt depend on registerMediator/removeMediator !BE AWARE! function removeNotificationListener(notificationName:String):void { org.puremvc.as3.core.View.getInstance().removeObserver(notificationName, this ); }
  45. 45. Пример использования: * Try to add view component in appropriate external slot. If there isnt * appropriate slot then start waiting for SLOT_CREATION_COMPLETE. function addViewComponentToExternalSlot():void { var desc:SlotViewComponentDescription = new SlotViewComponentDescription viewComponentName, viewComponentSlot, viewComponent as UIComponent ); var addNotification:INotification = new Notification( BaseNotifications.SLOT_VIEW_COMPONENT_ADD, desc, viewComponentSlot); facade.notifyObservers(addNotification); if(desc.viewComponent != null) // его бы обнулили если бы он был найден { addNotificationListener(BaseNotifications.SLOT_CREATION_COMPLETE, handleSlotCreationCompleteNotificationToAddViewComponent); } }

×