Ошибка: обложка для xxx не может быть найдена при добавлении IVisualElement, полученного из модуля Flex через пользовательское свойство

Я пытаюсь создать прототип модульной архитектуры приложений с использованием Apache Flex SDK 4.12.1 с использованием модулей Flex. У меня есть следующая структура проекта.

  1. CommonLib flex библиотека. Этот проект содержит один файл IPlugin.as, как показано ниже.

    {
        import mx.core.IVisualElement;
    
        public interface IPlugIn
        {
            function get MyPlugin():IVisualElement;
        }
    }
    
  2. Модуль FlexProject. Этот проект содержит два файла. PluginModule.mxml - модуль, который я хочу загрузить, и DemoForm.mxml - компонент, который я хочу добавить в основное приложение.

    // PluginModule.mxml
    <?xml version="1.0" encoding="utf-8"?>
    <s:Module xmlns:fx="http://ns.adobe.com/mxml/2009"
              xmlns:s="library://ns.adobe.com/flex/spark"
              xmlns:mx="library://ns.adobe.com/flex/mx"
              xmlns:local="*"
              implements="Interfaces.IPlugIn">
    
        <fx:Script>
            <![CDATA[
                import mx.core.IVisualElement;
    
                private var _myPlugin:DemoForm = new DemoForm();
    
                protected function button1_clickHandler(event:MouseEvent):void
                {
                    container.addElement(new DemoForm());
                }
    
                public function get MyPlugin():IVisualElement
                {
                    if (_myPlugin == null)
                        _myPlugin = new DemoForm();
    
                    return _myPlugin;
                }
    
            ]]>
        </fx:Script>
    
        <s:HGroup>
            <s:Button id="btn" label="Add DemoForm" click="button1_clickHandler(event)"/>
            <s:VGroup id="container"/>
        </s:HGroup>
    
    </s:Module>
    
    // Demoform.mxml
    <?xml version="1.0" encoding="utf-8"?>
    <s:Group xmlns:fx="http://ns.adobe.com/mxml/2009" 
             xmlns:s="library://ns.adobe.com/flex/spark" 
             xmlns:mx="library://ns.adobe.com/flex/mx" width="400">
    <s:layout>
        <s:TileLayout/>
    </s:layout>
    
        <s:Button label="Button 1"/>
        <s:TextInput/>
    </s:Group>
    
  3. FlexProject проект гибкого приложения. Он содержит один файл с намерением загрузить PluginModule и DemoForm.mxml в его BorderContainer.

    <?xml version="1.0" encoding="utf-8"?>
    <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
                   xmlns:s="library://ns.adobe.com/flex/spark" 
                   xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
    
        <fx:Script>
    
            <![CDATA[
                import mx.core.IVisualElement;
                import mx.events.ModuleEvent;
                import mx.modules.IModuleInfo;
                import mx.modules.ModuleManager;
                import Interfaces.IPlugIn;
    
                private var moduleInfo:IModuleInfo;
    
                protected function button1_clickHandler(event:MouseEvent):void
                {
                    moduleInfo = ModuleManager.getModule("PluginModule.swf");
                    moduleInfo.addEventListener(ModuleEvent.READY, renderModule);
                    moduleInfo.load(null, null, null, this.moduleFactory); 
                }
    
                private function renderModule(event:ModuleEvent):void
                {
                    var module:Object = moduleInfo.factory.create();
                    var plugin:IPlugIn = module as IPlugIn;
                    container.addElement(plugin as IVisualElement); // <-- Works!
                    container.addElement(plugin.MyPlugin);          // <-- Error: Skin cannot be found
                }
            ]]>
    
        </fx:Script>
    
        <mx:VBox>
            <s:Button click="button1_clickHandler(event)" label="Add Plugin"/>
            <s:BorderContainer id="container">
                <s:layout>
                    <s:VerticalLayout gap="10"/>
                </s:layout>
            </s:BorderContainer>
        </mx:VBox>
    </s:Application>
    

Я могу добавить модуль непосредственно в контейнер приложения, и все, кажется, работает. Контейнер приложения отобразит кнопку 1, реализованную PluginModule.mxml. Однако, когда я пытаюсь добавить Demoform в контейнер приложения с помощью метода plugin.MyPlugin, я получаю следующую ошибку.

Ошибка: обложка для FlexProject.ApplicationSkin2.containerGrp.contentGroup.VBox5.container.BorderContainerSkin10.Group11.DemoForm13.RadioButton16 не найдена.

Я пробовал это с многочисленными различными элементами управления, включая TextArea, TextInput и RadioButtons. Все они терпят неудачу с похожими ошибками. Похоже, что основное приложение не может найти скины для этих компонентов!

Интересно, что если я вместо этого позволю PluginModule.mxml добавить DemoForm.mxml в свой собственный контейнер, он будет работать нормально. Хотя, это не то поведение, которое я желаю.

Любые предложения относительно того, что может происходить и как я могу решить это?

2 ответа

Решение

Коллега нашла ответ. В проект, который будет загружать модули, нужно добавить -keep-all-type-selectors к параметрам компилятора. Согласно Adobe Docs...

-keep-все-типа-селекторы

Указывает компилятору сохранить селектор типа таблицы стилей в SWF-файле, даже если этот тип (класс) не используется в приложении. Это полезно, когда у вас есть модульное приложение, которое загружает другие приложения. Например, загружаемый SWF-файл может определять селектор типа для типа, используемого в загруженном (или целевом) SWF-файле. Если вы установите для этого параметра значение true при компиляции загружаемого SWF-файла, то целевой SWF-файл будет иметь доступ к этому селектору типов при его загрузке. Если для этого параметра установлено значение false, компилятор не будет включать этот селектор типа в загружаемый SWF-файл во время компиляции. В результате стили не будут доступны для целевого SWF-файла.

Это расширенный вариант.

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

Если вы хотите, чтобы неиспользуемые классы были включены, достаточно использовать импорт для этих классов. Убедитесь, что вы включили импорт в используемый класс.

Добавление флага компилятора "link-report filename" создает отчет, чтобы увидеть, какие классы включены.

Другие вопросы по тегам