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

发布于 2024-07-18 05:53:52 字数 1977 浏览 8 评论 0原文

我正在尝试为我们的应用程序实现一个插件系统,并且在获取动态加载的 SWF 文件、加载其他 SWF 文件时遇到了麻烦。

它是这样的:

  1. 主应用程序外壳加载...
  2. ---------+ 应用程序加载...
  3. -----------------+插件

我让应用程序 #1 加载应用程序 #2 没有问题

但是,尽我所能,我无法让应用程序 #2 加载并实例化 #3

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

有趣的是,当我将其提取到自己的应用程序中时,它工作得很好。 此问题是由于我从本身动态加载的 SWF 加载插件而触发的。

我相信这是由于 ApplicationDomain 造成的,但我无法弄清楚它的情况。 我尝试指定 currentDomainnew ApplicationDomain(Application.currentDomain)new ApplicationDomain() 但没有成功。

另外,值得注意的是,我无法在这两个应用程序中对 Foo 类进行硬引用,因为就其本质而言,我们不会提前知道它们将包含什么。

谷歌搜索了一下,这似乎是一个众所周知的问题,但我还没有找到(明确的)解决方案。

.
.
.
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");
        }
.
.
.
}

I'm trying to implement a plugin system for our application, and having a devil of a time getting SWF file which was dynamically loaded itself, load additional SWF files.

It goes something like this:

  1. Main Application Shell loads...
  2. ---------+ Application loads...
  3. -----------------+Plugin(s)

I have no problem getting app #1 to load app #2

However, try as I might, I cannot get app #2 to load and instantiate #3

I've tried various permutations using the ModuleManager, but this is the closest I get. When the onLoadComplete method get invoked, I can see that the SWF loaded, however the factory always returns NULL.

What is interesting is that when I extract this out in its own application, it works fine. This issue is triggered by the fact that I'm loading Plugin from a SWF that was loaded dynamically itself.

I believe this is due to the ApplicationDomain, but I cannot make heads or tails of it. I tried specifying currentDomain, new ApplicationDomain(Application.currentDomain) and new ApplicationDomain() without success.

Also, it is important to note that I cannot make reference a hard reference to the Foo class in either applications since by their nature, we will not know ahead of time what they will contain.

Googlin' around, this seems to be a fairly known problem, but I have not found a (clear) solution yet.

.
.
.
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
        {

        }
.
.
.
}

and

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");
        }
.
.
.
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

仄言 2024-07-25 05:53:52

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

var MyPlugin : 对象 = getPlugin();
MyPlugin.doPluginFunc();

一般来说,可以在系统/弹性类之间进行转换没有问题。 不知道将插件作为运行时库是否有帮助?

@ joshtynjala is right. I found try just using Object then calling methods on it (don't cast).

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

Generally can cast between system/flex classes no problem. Don't know if putting Plugin as a runtime library would help ?

泼猴你往哪里跑 2024-07-25 05:53:52

如果您确实想在插件和应用程序之间使用通用接口,则应用程序的 Plugin 类必须与插件的 Plugin 类相同。 为此,它们需要 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 时,您还将编译 Plugin。 这不是问题,但是您需要告诉您的应用程序它与他的应用程序相同:

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

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

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

If you really want to use a common interface between your plugin and your application, your application's Plugin class must be the same as your plugin's Plugin class. To do so, they need b to be in the same 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

The problem is, when you will compile your plugin swf, you will also compile Plugin. This is not a problem, but you need to tell your application that it's the same as his :

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

ApplicationDomain.currentDomain is the key here. If you refer to the docs :

Loader's own ApplicationDomain. You
use this application domain when using
ApplicationDomain.currentDomain. When
the load is complete, parent and child
can use each other's classes directly.
If the child attempts to define a
class with the same name as a class
already defined by the parent, the
parent class is used and the child
class is ignored.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文