Flex中ModuleManager的一个bug

估且认为它是一个bug吧,因为到目前为止还是没想明白造成问题的原因。

在相对较为复杂或是多人协作的flex项目开发中,使用module进行开发是很平常的事情,而module的加载一般常用的有两种方法:

1、使用ModuleLoader加载器;

2、使用ModuleManager进行加载;

 

使用ModuleLoader进行加载:

<mx:ModuleLoader id="moduleLoader" right="10" top="10"/>

//
private function loadModule(url:String):void
{
if (moduleLoader.url)
{
moduleLoader.unloadModule();
}

moduleLoader.url = url;
}

使用ModuleManager进行加载:

private function load(url:String):void
{
var tempModuleInfo:IModuleInfo = ModuleManager.getModule(url);

tempModuleInfo.addEventListener(ModuleEvent.READY, onReady);
tempModuleInfo.addEventListener(ModuleEvent.PROGRESS, onProgress);
tempModuleInfo.addEventListener(ModuleEvent.ERROR, onError);
tempModuleInfo.addEventListener(ModuleEvent.SETUP, onSetup);

tempModuleInfo.load(ApplicationDomain.currentDomain);
}

//...
private function onReady(evt:ModuleEvent):void
{
var tempModuleInfo:IModuleInfo = evt.target as IModuleInfo;

container.addChild(tempModuleInfo.factory.create() as DisplayObject);
}
 
ModuleManager类负责管理加载的模块,当将模块的url传递到public的ModuleManager.getModule方法中时,则该模块位置就添加到被管理模块的列表中,并返回一个mx.modules.IModuleInfo的实例。
ModuleInfo对象负责加载swf文件,并被封装成一个实现了IModuleInfo接口的代理类,由ModuleManager.getModule方法返回,可以监听代理类上的状态事件,比如:ready、error、setup、progress事件等.
 
mx.events.ModuleEvent类
常量字符串值描述
PROGRESS"progress"加载模块时被调度。可以用这个事件访问被加载模块的bytesLoaded和bytesTotal属性
SETUP"setup"当已加载了足够的模块内容时被调度
READY"ready"当模块完成加载时被调度
UNLOAD"unload"当卸载模块时被调度
ERROR"error"当模块下载过程中出错时被调度

 

但我在写实际的demo示例时,发现一个问题,如果没有事先声明IModuleInfo类的实例,在使用上面方面加载模块时,第一次加载不会调用任何的方法。完成的示例代码如下:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" minWidth="955" minHeight="600"
creationComplete="inited()">

<mx:Script>
<![CDATA[
import mx.events.ModuleEvent;
import mx.modules.IModuleInfo;
import mx.modules.ModuleManager;

private var module_1_url:String = "com/modules/OneModule.swf";
private var module_2_url:String = "com/modules/TwoModule.swf";

private var _moduleInfo:IModuleInfo;

private function inited():void
{

}

private function loadModule(type:Number):void
{
var url:String;

if (type === 1)
{
url = module_1_url;
}
else
{
url = module_2_url;
}

var tempModuleInfo:IModuleInfo = ModuleManager.getModule(url);

//注释或使用下面一行,运行查看不同的效果
_moduleInfo = tempModuleInfo;

tempModuleInfo.addEventListener(ModuleEvent.READY, onReady);
tempModuleInfo.addEventListener(ModuleEvent.PROGRESS, onProgress);
tempModuleInfo.addEventListener(ModuleEvent.ERROR, onError);
tempModuleInfo.addEventListener(ModuleEvent.SETUP, onSetup);

tempModuleInfo.load(ApplicationDomain.currentDomain);
}

private function onSetup(evt:ModuleEvent):void
{

}

private function onProgress(evt:ModuleEvent):void
{
msg.htmlText = "正在加载:" + Math.floor(evt.bytesLoaded / evt.bytesTotal).toString() + "%";
}

private function onReady(evt:ModuleEvent):void
{
var moduleInfo:IModuleInfo = evt.target as IModuleInfo;

moduleInfo.removeEventListener(ModuleEvent.PROGRESS, onProgress);
moduleInfo.removeEventListener(ModuleEvent.READY, onReady);
moduleInfo.removeEventListener(ModuleEvent.ERROR, onError);

msg.htmlText = "模块加载完成";

moduleCanvas.addChild(moduleInfo.factory.create() as DisplayObject);
}

private function onError(evt:ModuleEvent):void
{
msg.htmlText = "模块加载出错!";
}


private function useLoader():void
{
if (moduleLoader.url)
{
moduleLoader.unloadModule();
}

moduleLoader.url = module_1_url;
}
]]>
</mx:Script>

<mx:Text id="msg" />


<mx:HBox width="400" horizontalGap="10" y="50" x="50">
<mx:Button label="动态加载模块一" click="loadModule(1)" />
<mx:Button label="动态加载模块二" click="loadModule(2)" />
<mx:Spacer width="50" />
<mx:Button label="使用加载器" click="useLoader()" />
</mx:HBox>

<mx:ModuleLoader id="moduleLoader" right="10" top="10"/>

<mx:Tile horizontalGap="10" width="100%" id="moduleCanvas" y="100" />

</mx:Application>

在上面例子中,事先已经声明过了一个IModuleInfo类的实例,在加载时如果使用该实例进行加载则一切正常,如果不使用已经被声明过的实例加载,则第一次加载时,不会有任何的反应,但使用ModuleLoader是没有此问题的,所以我只能认为这是一个bug了

示例项目工程的目录很简单:

image

如果想使用ModuleManager加载模块,保险的方式就是先声明一个IModuleInfo类的实例,然后使用该实例去加载模块。两种加载模块的优先方法相比,一般更为常用的是第二种,因为可以预加载模块,比较容易按不同的需求来控制模块。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的UE5蓝图插件示例: 1. 新建一个C++插件工程,命名为MyBlueprintPlugin。 2. 在MyBlueprintPlugin.cpp实现以下代码: ```cpp #include "MyBlueprintPlugin.h" #include "Modules/ModuleManager.h" IMPLEMENT_MODULE(FMyBlueprintPluginModule, MyBlueprintPlugin) void FMyBlueprintPluginModule::StartupModule() { // 插件启动时执行的代码 } void FMyBlueprintPluginModule::ShutdownModule() { // 插件关闭时执行的代码 } ``` 3. 在MyBlueprintPlugin.h声明以下代码: ```cpp #pragma once #include "CoreMinimal.h" #include "Modules/ModuleManager.h" class FMyBlueprintPluginModule : public IModuleInterface { public: virtual void StartupModule() override; virtual void ShutdownModule() override; }; ``` 4. 在插件工程的Public目录下新建一个MyBlueprintFunctionLibrary.h文件,用于定义蓝图函数库,代码如下: ```cpp #pragma once #include "CoreMinimal.h" #include "Kismet/BlueprintFunctionLibrary.h" #include "MyBlueprintFunctionLibrary.generated.h" UCLASS() class UMyBlueprintFunctionLibrary : public UBlueprintFunctionLibrary { GENERATED_BODY() public: UFUNCTION(BlueprintCallable, Category = "MyBlueprintPlugin") static void MyFunction(); }; ``` 5. 在MyBlueprintFunctionLibrary.cpp实现蓝图函数,代码如下: ```cpp #include "MyBlueprintFunctionLibrary.h" void UMyBlueprintFunctionLibrary::MyFunction() { UE_LOG(LogTemp, Display, TEXT("Hello from MyBlueprintPlugin!")); } ``` 6. 编译插件工程,生成MyBlueprintPlugin插件。 7. 在UE5编辑器,创建一个新的蓝图,并在蓝图添加一个自定义节点,节点类型为MyBlueprintFunctionLibrary::MyFunction。 8. 在蓝图使用自定义节点,运行游戏,即可在输出日志看到“Hello from MyBlueprintPlugin!”的信息。 这就是一个简单的UE5蓝图插件示例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值