用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条件编译的知识,点击这里查看官方文档,或点击这里查看中文翻译。