我们都会通过FlashBuilder创建一个组件(component),
一般情况下,当主程序(Application)引用到此组件的时候,该组件就会被自动的创建出来。
如果主程序(Application)引用了太多的组件,那么主程序在创建的时候,就会很耗时。
- 为了提高主程序的启动效率
- 或者业务逻辑希望,某个组件不要马上被初始化
- 那么就需要让组件延迟加载(实例化)。
此时就需要使用 IdeferredInstance。
如何使用IdeferredInstance:
- IdeferredInstance是一个接口(mx.core.IDeferredInstance)
- UIComponents 都实现IdeferredInstance 接口
- 那么UIComponents 都可以通过调用getInstance()方法,去实例化(在你想要实例化的时候):
- 一个component(组件),内部包含的所有子组件,都可以根据自己的需要,事先定义成IDeferredInstance的对象(public var header:IDeferredInstance;)
- 或者将子组件集,放在数组里面,数组里面存储的都是IDeferredInstance的对象。
- 最后,在你想要实例化的时候,通过调用getInstance()方法,生成对象,再添加到可视化组件上,将他们都显示出来。
先看具体代码:
自定义组件(component)DeferredVBox.mxml:
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="400" height="300" borderStyle="solid" >
<fx:Script>
<![CDATA[
import mx.containers.HBox;
import mx.containers.ViewStack;
import mx.core.UIComponent;
// 定义IDeferredInstance的属性,至于它具体是哪个可视化组件,和该组件如何初始化, 在这里,我们可以先不去考虑
public var header:IDeferredInstance;
// 定义三个数组,声明数组里面所存储的对象都是 mx.core.IDeferredInstance的实例
// 在这里,至于这些数组是如何初始化, 和数组里面具体存储的是哪些可视化组件,我们可以先不去考虑
[ArrayElementType("mx.core.IDeferredInstance")]
public var leftDataRow:Array;
[ArrayElementType("mx.core.IDeferredInstance")]
public var centerDataRow:Array;
[ArrayElementType("mx.core.IDeferredInstance")]
public var rightDataRow:Array;
// 这种定义的方式,虽然是初始化对象是异步的,但是它得表述,规定了,此对象必须是HBox类的对象。
public var layoutHBox:HBox;
public var layoutWidth:int = 0;
/**
* 暴露一个公共方法,让程序可以随时根据逻辑需要,延迟初始化子组件
*
* */
public function createDeferredComponents():void {
addChild(UIComponent(header.getInstance()));
layoutHBox = new HBox();
if(layoutWidth != 0){
layoutHBox.setStyle("horizontalGap", layoutWidth);
}
if(leftDataRow.length > 0){
var leftVBox:VBox = new VBox();
layoutHBox.addChild(leftVBox);
for (var i:int = 0; i < leftDataRow.length; i++){
leftVBox.addChild(UIComponent(leftDataRow[i].getInstance()));
}
}
if(centerDataRow.length > 0){
var centerVBox:VBox = new VBox();
layoutHBox.addChild(centerVBox);
for (var i:int = 0; i < centerDataRow.length;
i++)
{
centerVBox.addChild(UIComponent(centerDataRow[i].
getInstance()));
}
}
if(rightDataRow.length > 0){
var rightVBox:VBox = new VBox();
layoutHBox.addChild(rightVBox);
for (var i:int = 0; i < rightDataRow.length;
i++)
{
rightVBox.addChild(UIComponent(rightDataRow[i]
.getInstance()));
}
} // Add the HBox container to the VBox container.
addChild(layoutHBox);
}
]]>
</fx:Script>
</mx:VBox>
主程序(application): DeferredTest.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" xmlns:local="*">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
/**
* 比如,根据业务逻辑需要,只有在Button点击的时候,才开始创建DeferredVBox里面的子组件。
* 注意,是DeferredVBox里面的子组件是延迟初始化的!而不是DeferredVBox本身,
* 在这里DeferredVBox,我故意给他一个黑色边框,
* 可见,在主程序初始化的时候,DeferredVBox本身,已经渲染好了,
* 当点击Button,才开始创建DeferredVBox里面的子组件得内容!!!!
* */
private function createDeferredInstance():void
{
this.deferredInstance.createDeferredComponents();
}
]]>
</fx:Script>
<mx:VBox>
<mx:Button click="createDeferredInstance()"
label="make components"/>
<local:DeferredVBox layoutWidth="30"
id="deferredInstance">
<!-- 通过标签赋值, 此时告诉DeferredVBox.header属性,它就是Label可视化组件(<span style="font-family: Arial, Helvetica, sans-serif;">Label </span>extends UIComponent) -->
<!-- 此时,仅仅是完成描述定义的过程, 还没有实例化对象-->
<local:header>
<mx:Label text="This will be the header of my templated
component"/>
</local:header>
<!-- 通过标签赋值, 此时leftDataRow数组被初始化:告诉数组里面存储的是3个Label -->
<!-- 此时,仅仅是完成描述定义的过程, 还没有实例化对象-->
<local:leftDataRow>
<fx:Array>
<mx:Label text="data"/>
<mx:Label text="data"/>
<mx:Label text="data"/>
</fx:Array>
</local:leftDataRow>
<!-- 通过标签赋值, 此时centerDataRow数组被初始化: 告诉数组里面存储的是一个Label和一个Button -->
<!-- 此时,仅仅是完成描述定义的过程, 还没有实例化对象-->
<local:centerDataRow>
<fx:Array>
<mx:Button label="press me"/>
<mx:Label text="data"/>
</fx:Array>
</local:centerDataRow>
<!-- 通过标签赋值, 此时rightDataRow数组被初始化: 告诉数组里面存储的是一个Label,一个CheckBox和一个Button -->
<!-- 此时,仅仅是完成描述定义的过程, 还没有实例化对象-->
<local:rightDataRow>
<fx:Array>
<mx:CheckBox label="click"/>
<mx:Button label="press me"/>
<mx:Label text="data"/>
</fx:Array>
</local:rightDataRow>
</local:DeferredVBox>
</mx:VBox>
</s:Application>
运行截图: