在 Flex 中创建插件 - 加载嵌套的 SWF 文件
我正在尝试为我们的应用程序实现一个插件系统,并且在获取动态加载的 SWF 文件、加载其他 SWF 文件时遇到了麻烦。
它是这样的:
- 主应用程序外壳加载...
- ---------+ 应用程序加载...
- -----------------+插件
我让应用程序 #1 加载应用程序 #2 没有问题
但是,尽我所能,我无法让应用程序 #2 加载并实例化 #3
我已经使用 ModuleManager 尝试了各种排列,但这是我得到的最接近的排列。 当调用 onLoadComplete 方法时,我可以看到 SWF 已加载,但工厂始终返回 NULL。
有趣的是,当我将其提取到自己的应用程序中时,它工作得很好。 此问题是由于我从本身动态加载的 SWF 加载插件而触发的。
我相信这是由于 ApplicationDomain
造成的,但我无法弄清楚它的情况。 我尝试指定 currentDomain
、new 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:
- Main Application Shell loads...
- ---------+ Application loads...
- -----------------+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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
@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 ?
如果您确实想在插件和应用程序之间使用通用接口,则应用程序的 Plugin 类必须与插件的 Plugin 类相同。 为此,它们需要 b 位于同一个 ApplicationDomain 中。
问题是,当您编译插件 swf 时,您还将编译 Plugin。 这不是问题,但是您需要告诉您的应用程序它与他的应用程序相同:
ApplicationDomain.currentDomain 是这里的关键。 如果您参考 文档 :
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.
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 :
ApplicationDomain.currentDomain is the key here. If you refer to the docs :