小记:
时隔3年游戏开发后又回到了Flex的开发上面来。虽然现在的Flex的热度已经大不如以前,甚至到了Flex SDK 4.7 版本Adobe Flash Builder 干脆连设计试图都不支持了。如今的Flex SDK, 4.6, 4.7 已经和之前大不一样了。比如之前的滚动的处理实现,CSS样式域的问题,现如今都得到了一一支持。但是不管怎么样Flex SDK 的优越性在目前市面上所有的Flash UI FrameWork中,他们都是无法比拟的。
再次接触Flex sdk 发现还是有点不尽人意的地方,比如在主题样式和资源这块。在project Compile Option中加入-keep-generated-actionscript 参数时会在项目的bin文件下生成对应的Actionscript代码。如下图:
其中包含了默认的Locale 资源和 默认的Theme 资源。
对于Locale 资源我们可以在project Compile Option 加入 -locale, 这样默认的一套Locale Resource就可以做成ResourceModual 了, 而且是可以RSls加载支持的。
但是对于Defualt Theme 这块是去不掉的, 如果每个Project都一样的花,这个有点浪费资源了,虽然不大到目前为止(除掉Locale Resource)一个空的Project 大概38K。
对于Local 的资源我的构想是 Default Local Resource Modual + Custom Defined Local Resource Modual
对于样式这块的资源我的构想是 defualt Theme Modual + Global CSS Style Modual + Custom CSS Style Modual
对于样式这块,采用Rsls方式去实现,估计是不可能的,可以去看下生成的代码。不但是这样,就连我想加一个全局样式模块都不可以。
大概能使用的就是,在Application 中 使用styleManager.loadStyleDeclarations()去加载了,或者在Custom Preload Bar中去加载,但是不管怎么样,一定是在Application初始化后才能做的。
下面我来介绍一中方式,大概和Rsls类似的效果,而且是在New Application 之前发生的。 但是,为什么一定要纠结在 new Appication 之前,因为运行时切换皮肤是很耗资源的能不要这样做就不要这样做。
看下实现过程:
package com.citi.crm.flex { import flash.display.DisplayObject; import flash.events.IEventDispatcher; import flash.events.ProgressEvent; import mx.core.IFlexModuleFactory; import mx.core.mx_internal; import mx.events.StyleEvent; import mx.managers.ISystemManagerChildManager; import mx.managers.systemClasses.ChildManager; import mx.styles.IStyleManager2; use namespace mx_internal; [Mixin] public class FakeChildManager implements ISystemManagerChildManager { private static var _instance:FakeChildManager; private static var _styleURL:String; public static function init(fbs:IFlexModuleFactory):void { // _styleURL = "ClientInsightCRM_GlobalStyle.swf"; _styleURL = Object(fbs).loaderInfo.parameters.gStyleURL; if(_styleURL) { //for hold the instance _instance = new FakeChildManager(fbs); } } private var _systemManager:Object; private var _realChildManager:ISystemManagerChildManager; private var _styleLoadWatcher:IEventDispatcher; public function FakeChildManager(systemManager:IFlexModuleFactory) { super(); _systemManager = systemManager; _realChildManager = _systemManager["childManager"]; _systemManager["childManager"] = this; } //ISystemManagerChildManager Interface public function initializeTopLevelWindow(width:Number, height:Number):void { //just complete initializeTopLevelWindow function instead in hakc way. doOurLoadingFlow(); } protected function doOurLoadingFlow():void { var styleManager:Object = _systemManager.getImplementation("mx.styles::IStyleManager2"); _styleLoadWatcher = IEventDispatcher(Object(styleManager).loadStyleDeclarations(_styleURL, false)); _styleLoadWatcher.addEventListener(StyleEvent.PROGRESS, gStyleProgressHandler); _styleLoadWatcher.addEventListener(StyleEvent.COMPLETE, gStyleCompleteHandler); _styleLoadWatcher.addEventListener(StyleEvent.ERROR, gStyleErrorHandler); } protected function onDoOurLoadingFlowEnd():void { _styleLoadWatcher.removeEventListener(StyleEvent.PROGRESS, gStyleProgressHandler); _styleLoadWatcher.removeEventListener(StyleEvent.COMPLETE, gStyleCompleteHandler); _styleLoadWatcher.removeEventListener(StyleEvent.ERROR, gStyleErrorHandler); _styleLoadWatcher = null; _systemManager["childManager"] = _realChildManager; _realChildManager.initializeTopLevelWindow(_systemManager.width, _systemManager.height); _realChildManager = null; _systemManager = null; _instance = null; _styleURL = null; } public function addingChild(child:DisplayObject):void {}; public function childAdded(child:DisplayObject):void {}; public function childRemoved(child:DisplayObject):void {}; public function removingChild(child:DisplayObject):void {}; //event handler private function gStyleProgressHandler(event:StyleEvent):void { IEventDispatcher(_systemManager.preloader).dispatchEvent(new ProgressEvent(ProgressEvent.PROGRESS, false, false, event.bytesLoaded, event.bytesTotal)); } private function gStyleCompleteHandler(event:StyleEvent):void { onDoOurLoadingFlowEnd(); } private function gStyleErrorHandler(event:StyleEvent):void { //just skip it onDoOurLoadingFlowEnd(); } } }
一定 需要将此类引用到项目中,不然不会作用的。
Mixin 元标签是保证,在new Application 之前调用 public static function init(fbs:IFlexModuleFactory):void 执行代码。而且在构造函数里面我们偷偷换掉了SystemManager 中的ChildManager的引用对象,改为当前,
因为我们就是要阻止实际的ChildManager的initializeTopLevelWindow()函数的执行, 在FakeChildManager 的initializeTopLevelWindow,
我们来做自己的事情,等完成后在把SystemManager 中的ChildManager引用换成原来真实的ChildManager 对象, 并调用initializeTopLevelWindow。
这种方式我认为是最简洁的实现Css modual Rsls 的加载方式。 你们有什么好办法?