在Flex中创建插件 - 加载嵌套的SWF文件

时间:2009-04-27 12:30:17

标签: flex actionscript-3 plugins applicationdomain

我正在尝试为我们的应用程序实现一个插件系统,并且有一段时间获取自动动态加载的SWF文件,加载其他SWF文件。

它是这样的:

  1. 主要应用程序Shell加载...
  2. --------- +应用程序加载......
  3. ----------------- +插件(S)
  4. 我没有问题让app#1加载app#2

    但是,尽我所能,我无法让app#2加载并实例化#3

    我已尝试使用ModuleManager进行各种排列,但这是我得到的最接近的排列。当调用onLoadComplete方法时,我可以看到加载了SWF,但是工厂总是返回NULL。

    有趣的是,当我在自己的应用程序中提取它时,它工作正常。这个问题是由我从一个动态加载的SWF加载插件这一事实引发的。

    我认为这是ApplicationDomain所致,但我无法做出正面或反面。我尝试指定currentDomainnew ApplicationDomain(Application.currentDomain)new ApplicationDomain()但没有成功。

    另外,重要的是要注意,我不能在任何一个应用程序中引用Foo类的硬引用,因为就其性质而言,我们不会提前知道它们将包含什么。

    googlin',这似乎是一个众所周知的问题,但我还没有找到(明确的)解决方案。

    .
    .
    .
    assetModule = ModuleManager.getModule("Foo.swf");    
    assetModule.addEventListener(ModuleEvent.READY, onLoadComplete );
    assetModule.addEventListener(ModuleEvent.ERROR, onLoadError);
    assetModule.load();
    .
    .
    .
    private var _pluginInstance:Plugin;
    
    private function onLoadComplete( event:Event ):void
    {
        trace("module loaded");
    
        _pluginInstance = assetModule.factory.create() as Plugin;
        if( _pluginInstance )
            _pluginInstance.startup();
        else 
            Alert.show("unable to instantiate module");
    }
    
    private function onLoadError( event:Event ):void
    {
           Alert.show("error");
    }
    
    My Plugin looks like this:
    
    package
    {
        import mx.collections.ArrayCollection;
        import mx.modules.ModuleBase;
    
            public class Plugin extends ModuleBase
    
            public function startup():void
            {
    
            }
    .
    .
    .
    }
    

    package 
    {
        import Plugin;
        import mx.modules.ModuleBase;
    
        public class Foo extends Plugin
        {
            public function Foo()
            {
                trace("foo constructor invoked");
            }
    
            override public function startup():void
            {
                        trace("foo started");
            }
    .
    .
    .
    }
    

2 个答案:

答案 0 :(得分:0)

@ joshtynjala是对的。我发现尝试只使用Object然后调用它的方法(不要强制转换)。

var MyPlugin:Object = getPlugin(); MyPlugin.doPluginFunc();

一般可以在系统/ flex类之间强制转换没问题。不知道将Plugin作为运行时库是否有帮助?

答案 1 :(得分:0)

如果您真的想在插件和应用程序之间使用通用接口,那么您的应用程序的插件类必须与插件的插件类相同。为此,他们需要b在同一个ApplicationDomain中。

//In an external library
public interface Plugin {}

//In your application
_pluginInstance = assetModule.factory.create() as Plugin;
...


//In your plugin
public class MyPlugin implements Plugin

问题是,当你编译你的插件swf时,你也会编译插件。这不是问题,但您需要告诉您的应用程序它与他的相同:

var loader:Loader = new Loader();
loader.addEventListener(Event.COMPLETE, onLoadComplete);
loader.load(new URLRequest("plugin.swf"), new LoaderContext(false, ApplicationDomain.currentDomain));    

ApplicationDomain.currentDomain是这里的关键。如果您参考docs

  

Loader自己的ApplicationDomain。您   使用时使用此应用程序域   ApplicationDomain.currentDomain来。什么时候   负载是完整的,父母和孩子   可以直接使用彼此的类。   如果孩子试图定义一个   与类同名的类   已经由父母定义了   使用父类和孩子   class被忽略了。