有一定开发经验的程序员都习惯把一些可配置的信息内容存放在自定义的配置文件中,当需要改变配置时,只需要修改配置文件即可,不需要重新编译发布程序。
正常情况下,在Flex中读取自定义配置文件不是什么难事,但有时候要求在Application初始化之前必须获得完整配置信息,这样的话必须下一点功夫了。
Application初始化之前能够操作的地方就只有preloader了,如果把读取自定义配置文件跟preloader下载类库看作相同处理的话,基本就能达到功能。
注意:preloader只能使用flash和部分mx命名空间的类库,千万别使用mx和spark控件类库,否则preloader的工作就不是预加载了。
自定义配置信息类:
public class Config { public static const URL:String = "config.xml"; private static var _instance:Config; public static function getInstance():Config { if (_instance == null) _instance = new Config(); return _instance; } private var _config:XML; public function get config():XML { return _config; } public function set config(value:XML):void { _config = value; } }
加载自定义配置文件就在preloader把所有类库下载完毕,application初始化之前进行,于是这里拦截preloader的PRELOADER_DOC_FRAME_READY事件
public class SparkPreloader extends SparkDownloadProgressBar { private var _preloader:Sprite; private var suspend:Boolean; private var _urlLoader:URLLoader; public function SparkPreloader() { super(); } override public function set preloader(value:Sprite):void { _preloader = value; super.preloader = value; value.addEventListener(FlexEvent.PRELOADER_DOC_FRAME_READY, preloaderDocFrameReadyHandler, false, int.MAX_VALUE); //添加最高级别监听 } private function preloaderDocFrameReadyHandler(event:FlexEvent):void { //停止初始化Application event.stopImmediatePropagation(); if (suspend) return; suspend = true; //挂起 startConfiguation(); //启动配置 } private function startConfiguation():void { _urlLoader = new URLLoader(); _urlLoader.addEventListener(Event.COMPLETE, completeHandler); _urlLoader.load(new URLRequest(Config.URL)); } private function completeHandler(e:Event):void { _urlLoader.removeEventListener(Event.COMPLETE, completeHandler); Config.config = new XML(_urlLoader.data); _urlLoader = null; _preloader.removeEventListener(FlexEvent.PRELOADER_DOC_FRAME_READY, preloaderDocFrameReadyHandler); //移除监听 _preloader.dispatchEvent(new FlexEvent(FlexEvent.PRELOADER_DOC_FRAME_READY)); //继续初始化Application } }
Flex的启动过程参考《浅析Flex启动过程》
简单说就是Flex归根结底还是swf,跟flash一样有时间轴和帧,只是Flex通常情况下只有两帧,第一帧是preloader,第二帧才是application。平时我们看到的loading界面就是第一帧的preloader,当下载完成后跳转到第二帧初始化application,并派发出PRELOADER_DOC_FRAME_READY事件。为了能在application初始化前读取配置内容,必须监听PRELOADER_DOC_FRAME_READY事件,并且必须是最高级别的监听,因为SystemManager中就是监听到PRELOADER_DOC_FRAME_READY事件后执行第二帧的初始化工作,而且SystemManager我们很难修改。代码中我借用了我《Flex中实现模块顺序执行》文中方法,如果有多个配置需要读取,或者还有其他初始化工作,则在通过addChild添加。因为PRELOADER_DOC_FRAME_READY事件是不断派发出来的,故我加上suspend标识防止重复处理,直到配置读取完成后,移除监听器并主动派发PRELOADER_DOC_FRAME_READY事件事件,让SystemManager继续工作。
经测试,再也没有报错了。我觉得这应该是最完美的解决方案了。