我正在尝试使用Flex模块利用Apache Flex SDK 4.12.1对模块化应用程序架构进行原型设计。我有以下项目结构。
CommonLib flex库。该项目包含一个文件IPlugin.as,如下所示。
{
import mx.core.IVisualElement;
public interface IPlugIn
{
function get MyPlugin():IVisualElement;
}
}
ModuleProject flex应用程序。该项目包含两个文件。 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>
FlexProject flex应用程序项目。这包含一个文件,旨在将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>
我可以将模块直接添加到应用程序的容器中,一切似乎都有效。然后,应用程序容器将显示PluginModule.mxml实现的1按钮。但是,当我尝试通过plugin.MyPlugin方法将Demoform添加到应用程序的容器时,我收到以下错误。
错误:皮肤为 FlexProject.ApplicationSkin2.containerGrp.contentGroup.VBox5.container.BorderContainerSkin10.Group11.DemoForm13.RadioButton16 无法找到。
我尝试过很多不同的控件,包括TextArea,TextInput和RadioButtons。这些都失败了类似的错误。看来主应用程序无法找到这些组件的皮肤!
有趣的是,如果我改为允许PluginModule.mxml将DemoForm.mxml添加到它的拥有容器中,它可以正常工作。虽然,这不是我想要的行为。
有关可能发生的事情以及我如何处理它的任何建议?
答案 0 :(得分:0)
我认为您的模块省略了所需的类,这些类在主应用程序中也不可用。
如果要包含未使用的类,则在这些类上使用导入就足够了。确保将导入包含在正在使用的类中。
添加编译器标志&#34; link-report filename&#34;生成报告以查看包含哪些类。
答案 1 :(得分:0)
一位同事找到了答案。在将加载模块的项目中,您需要将-keep-all-type-selectors
添加到编译器选项中。根据{{3}} ...
-keep-所有类型选择器
指示编译器在SWF中保留样式表的类型选择器 文件,即使该类型(类)未在应用程序中使用。 当您具有加载其他模块化应用程序时,这非常有用 应用。例如,加载SWF文件可能会定义类型 加载(或目标)SWF文件中使用的类型的选择器。如果你 在编译加载SWF文件时将此选项设置为true,然后是 目标SWF文件可以访问该类型选择器 加载。如果将此选项设置为false,则编译器将不包括 编译时加载SWF文件中的类型选择器。作为一个 结果,样式将无法用于目标SWF文件。
这是一个高级选项。