使用 Adob​​e AIR 构建插件架构

Posted

技术标签:

【中文标题】使用 Adob​​e AIR 构建插件架构【英文标题】:Building a Plugin Architecture with Adobe AIR 【发布时间】:2010-09-25 13:46:43 【问题描述】:

我正在考虑选择 Adob​​e AIR 作为即将到来的项目的客户端实施技术。 (之前的选择是 C# 和 WPF,但最近对 Flash/Flex/AIR 印象深刻。)

但我的产品最重要的功能之一是它的插件架构,它允许第三方开发人员以有趣的方式扩展功能和 GUI。

我知道如何在 C# 中设计架构:插件加载器会枚举本地“app/plugins/”目录中的所有程序集。对于每个程序集,它会枚举所有类,寻找“IPluginFactory”接口的实现。对于工厂创建的每个插件,我都会询问它的 MVC 类,并将其 GUI 元素(菜单项、面板等)嵌入现有 GUI 布局中的适当插槽中。

我想在 AIR 中完成同样的事情(从本地文件系统加载插件,而不是从 Web 加载)。在阅读this article 之后,我的理解是这是可能的,并且基本架构(将 SWF 加载到沙盒应用程序域等)与您在 .NET 中的方式非常相似。

但我很好奇其中的陷阱。

如果你们中的任何人使用 Flash 播放器进行了任何动态类加载(最好是在混合的 flash/flex 应用程序中,特别是在 AIR 主机中),我很想听听您构建插件框架的经验以及您在哪里运行使用 flash 播放器、flash、flex 和 AIR API 处理棘手的情况。

例如,如果有人问我同样的问题,但考虑到 Java 平台,我肯定会提到 JVM 没有“模块”或“程序集”的概念。***别的聚合是“类”,因此很难在插件系统中创建组织结构来管理大型项目。我还将讨论多个类加载器的问题,以及每个类加载器如何维护自己独立的加载类实例(具有自己独立的静态变量)。


以下是一些对我来说仍未得到解答的具体问题:

1) 动作脚本“Loader”类可以将 SWF 加载到 ApplicationDomain。但是那个 appdomain 到底包含什么?模块?上课? MXML 组件是如何表示的?如何找到所有实现我的插件接口的类?

2) 如果您已将插件加载到与主应用程序不同的 ApplicationDomain 中,那么从该其他应用程序域中调用代码是否会更加复杂?对于可以通过跨应用程序域编组层的数据类型是否有任何重要限制?编组是否过于昂贵?

3) 理想情况下,我想将自己的大部分主代码开发为插件(主应用程序只不过是一个插件加载外壳),并使用插件架构将该功能提升到应用程序中.是不是让你心生恐惧?

【问题讨论】:

【参考方案1】:

回应关于 Java 作为一种可能的插件架构的声明:

事实证明,Java 多年来一直被用于设计插件架构系统。至于客户端,Equinox OSGi 模块管理框架可能是最著名的。有一次,Eclipse IDE 在 Equinox OSGi 之上重构了他们的插件架构。 Eclipse IDE 可能是迄今为止设计的最成功的客户端插件体系结构系统之一——从历史的寿命以及用户群的广度和插件开发的后续社区的角度来看。他们还提供插件架构作为设计任意客户端应用程序的基础框架 - Eclipse RCP。

我不得不插话,因为尽管 Java 被定位为可能是一个非常薄弱的​​选择,但它实际上比迄今为止的任何其他语言/运行时环境在交付此类工作系统方面都要成功得多 - 尤其是与 C# 相比.NET,当然,它天生就有很好的模块功能。有点讽刺,但你有它。

至于 Adob​​e AIR,我正在开发管理一个正在 AIR 上设计的项目。在我们的例子中,我们的模块可扩展性总是从 Web 服务器交付——而不是本地目录。 Flex 有

<mx:Module/>

用于创建可在运行时离散加载的模块的标签。

唉,AIR 令人沮丧的是它缺少用于启动其他应用程序的任何类 API。您可以加载 URL 以在用户的​​默认浏览器中加载某些内容,但您无法启动 Excel。 Java 和 C# 都有用于将其他应用程序作为外部进程启动的 API。

【讨论】:

【参考方案2】:

您是否尝试过加载子应用程序? 在 AIR 中有很好的文档可以做到这一点,我在几个小时内就成功了。然而,由于子应用程序和主应用程序之间的沙箱冲突,相同的实现在 Flex 中是不同的故事。我花了数周时间把头撞到墙上。

【讨论】:

【参考方案3】:

Luca Tettamanti 已经对您的具体问题给出了很好的回答,所以我将提供一些关于一般主题的额外信息:

我已经使用ModuleManager 类(以及mx.modules 包中的其他东西)为Flex 应用程序实现了一个简单的插件API。它的要点是你从ModuleBase 子类化插件并使用@ 987654330@ 在主机应用程序中加载它们。然后你让插件实现一个通用接口(例如IMyAppPlugin)并使用某种facade来表示和实现插件可以使用的主机应用程序接口(例如MyAppFacade implements IMyAppFacade。)每当加载插件时,将此外观引用注入其中。

Flex 3 帮助中的主题"Modular applications overview" 提供了一些很好的信息(“模块域”子章节讨论了模块上下文中的应用程序域。)以下是摘录:

"默认情况下,一个模块被加载到当前的子域中 应用领域。您可以指定一个 通过使用不同的应用程序域 的 applicationDomain 属性 ModuleLoader 类。”

主题"Using the ApplicationDomain class" 更深入地探讨了应用程序领域的主题,如果您还没有阅读过,那么您绝对应该阅读它。

【讨论】:

非常好。你的插件 API 是开源的吗? 不,即使是这样,它也非常特定于为其编写的应用程序。我写的答案中几乎解释了所有“通用”的内容。 明白了。我会看看你的链接。 (上周才开始接触 flex,所以我对 flex 模块还不太了解。)不过还有一个问题……在可插入的 AIR 应用程序中,我希望用户能够安装 插件。鉴于 AIR 的标准安装程序,您建议如何处理? 我自己也在考虑这个问题……不幸的是,我并不是 AIR 方面的专家——我只是涉足它。对不起。 :( 或许你可以自己在app UI中实现插件的安装,并使用File.applicationStorageDirectory下的一些路径作为安装插件的位置。 应该检查在 Flex SDK 3.2 中添加的子应用程序功能 - 这就是做问题中描述的事情:livedocs.adobe.com/flex/3/loading_applications.pdf 切入正题 - 使用 子应用程序加载,因为它为此功能进行了增强【参考方案4】:
    applicationDomain 更像是一个命名空间,它将类定义分组并放入层次结构中:一个域可以直接访问自己域或父域中的符号,但 不能 访问子域中的符号或兄弟域(或更好:它不能直接这样做 - 它必须通过 applicationDomain 对象,询问给定类的定义);加载外部 swf 时,您可以决定 where 放置新符号:子域(默认)、附加到系统的新域(使用 null)、当前域,附加在其他地方的域(显式传递新域的父域)。请注意,新符号永远不会覆盖当前域中的符号,但同名可以存在于多个域中。 不幸的是,您无法枚举给定域中的类(好吧,至少我不知道有什么方法),但常见的解决方案是要求(如“插件接口”中)存在一个众所周知的每个 swf 中的工厂,它将返回插件的定义(类)或插件本身。 您只需以某种方式获取对象的引用(工厂),然后它只是另一个对象。没有编组:域只是命名空间的逻辑分区(它是系统域的树分支)。 否 :) 但请注意:它可能很容易变成 GC 的地狱,由于引用散布在其他域中而无法卸载未使用的域。我建议看一下多核 PureMVC 框架,可能使用管道来确保插件之间的严格分离。

顺便说一句,Flash Player 也是一个安全域的概念,但我实际上从未接触过它,所以我不知道这里有什么可能性。

【讨论】:

以上是关于使用 Adob​​e AIR 构建插件架构的主要内容,如果未能解决你的问题,请参考以下文章

使用 Adob​​e Air 生成静音音频文件

如何在 Adob​​e Air Mobile 的 Android 原生扩展中包含额外的 Jar

使用 Adob​​e AIR 下载文件

在没有开发许可证的情况下在 iOS 上测试 Adob​​e AIR 移动应用程序

使用 Adob​​e AIR 获取外部 IP

Android SDK 到 Adob​​e Air