利用条件编译解决iOS和Android的ANE冲突

用Adobe Air开发移动应用的一大优点是其通用性,就是可以一套代码可以在iOS和Android两大平台上运行。

但是Air是跑在虚拟机上的,有一些系统的原生函数我们不能通过Air来访问。Adobe提供了ANE来实现一些Air不能实现的本机功能。遗憾的是在用Flash Builder编译iOS的版本时,Android版本的ANE是不能编译进去的,反之也是一样。

这个冲突的的一个解决办法是注释代码或引用。但是是当ANE的引用分布在各个类的时候,这个问题会显得尤其麻烦。

其实,我们可以将通用的ANE尽可能的抽象出来,加之以良好的封装,然后利用条件编译来解决这个问题。

以下将通过一个例子,来阐述我对这个问题的解决方法。

试想有两个ANE,一个是iOS的ANE,一个是Android的ANE,然后我们执行以下几步。

1.对ANE进行抽象封装

我们可以将这两个ANE中相似的功能提取出来。

比如两个ANE都有调用系统窗口的函数,可以新建一个类SysWindowANE,以这个类为基类。声明接口警告alert(msg)和确认confirm(title, msg)等等接口。然后对iOS和Android的ANE各写一个子类,继承这个基类,在子类里引用ANE代码,实现具体的调用。

这样一来,我们可以把具体的ANE的引用全部交给子类,而这个基类干净整洁,跟具体的ANE没有关联。

2.将差异尽可能集中

有了一个基类,我们可能会在代码中四处引用这个基类的方法,来达到真正的调用系统窗口的目的。

但是也就意味着这个基类的引用会散落在代码各处。万一两个子类有差异化的方法,就必然需要通过(instance as Class).function这种方式来实现子类的引用,也就意味着有可能引用了ANE代码的子类会散落在代码各处。

我们可以新建一个管理类SysWindowANEManager,来解决这个问题。

在这个管理类中,我们可以生成一个类型为SysWindowANE的静态成员sysWinANE。在管理类中,我们将这个SysWindowANE的所有公共接口重新封装一次,使得所有可以通过访问SysWindowANE的方法,统统都可以通过这个管理类得到。如此,在全局代码中,只有SysWindowANEManager引用了SysWindowANE

3.利用条件编译解决编译冲突

做好了前面的抽象和封装工作后,我们可以添加以下的编译器参数:

-define+=CONFIG::isIOS,true
-define+=CONFIG::isAndroid,false

然后在SysWindowANEManager中,我们可以通过这组参数来实现条件编译。

譬如,两个ANE的init方法不一致,我们可以在SysWindowANEManager中的init方法中这么写:

CONFIG::isIOS
{
    //init ios ane here
    (sysWinANE as IosSysWindowANE).init(...)
}
CONFIG::isAndroid
{
    //init android ane here
    (sysWinANE as AndroidSysWindowANE).init(...)
}

如果在编译器参数中把isIOS设为true,isAndroid设为false的话,CONFIG::isAndroid语句块中的代码将不会被编译,反之一样。

由于之前的封装工作保证了对ANE实际代码的引用只会出现在SysWindowANEManager内,也就意味着不用注释任何引用或代码,只需改变编译器参数的设置,就可实现iOS和Android的ANE的共存。

想了解更多关于Flex条件编译的知识,点击这里查看官方文档点击这里查看中文翻译

关注微信公众号:timind

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注