小记:
时隔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 的加载方式。 你们有什么好办法?