Application和UIComponent的初始化过程涉及到很多方面,若揉杂在一起便会对维护和修改造成混乱的局面,于是Flex将初始化过程进行阶段划分并制定执行顺序,每个阶段完成都会触发一个事件,这些事件不仅能够反映初始化过程,还为我们提供了对初始化进行增补的手段。

UIComponent初始化流程

Flex组件和Flex容器都继承UIComponent,它们的初始化流程都被定义在UIComponent中,这表示Flex组件和Flex容器的初始化流程是相同的,Flex组件虽然不能象容器那样添加子级,但不代表它们没有子级,如Button内部包含的UITextField,某些Flex组件和Flex容器一样包括其它Flex组件,如Combox的子级包括List组件,这样的组件称为复合组件。Flex组件和Flex容器均采取递归的方式初始化,即先完成子级初始化,然后完成父级初始化,在初始化过程中伴随者事件,如图:


在UIComponent的构造函数中不会创建组件的子级,构造函数中只对组件的默认属性、样式进行设置,并且为组件添加侦听器,子级是在initilize()方法中创建的,initilize()方法是UIcomponent初始化核心,它不由构造函数调用的,而是调用addChild()和addChildAt()方法时执行,好处是节省内存占用,初始化后的组件必然要占据大量的内存,动态添加的子级在加入容器之前保持其最小体积,直到加入容器时才具有正常的内存占用。

在createChildren()方法中创建组件的子级,如果子级也是UIComponent,则会产生递归,preInitilize事件提供创建子级之前的准备工作,childrenCreated()和initilizationComplete()方法提供子级创建完毕之后的改造工作,区别是它们之间相隔一个initializeAccessibility()方法,initializeAccessibility()用于初始化辅助功能,当所有子级以及递归完成后,发送initilize事件,如果UIComponent是容器,则接着对组件进行布局,布局完成后发送creationComplete事件。

了解initilize()方法工作原理对开发自定义组件非常重要,选择继承UIComponent时,应该把创建子级的代码放入createchildren()方法中;选择继承内置组件时,可以在childrenCreated()或initilizationComplete()方法中对组件进行改造;如果只需要对组件的属性或者样式进行设置,可以选择preInitilize、initilize事件在不同阶段进行设置,要修改布局,可在creationComplete事件后进行。

Application初始化流程

Application的初始化过程不但包括内部子级的初始化,还通知SystemManager将其加入舞台的显示列表,Application是Flex容器,它的初始化规则遵守普通组件的规则,这里以事件为主线阐明Application在初始化过程中经历的阶段:



Application拥有普通容器设有的ApplicationComplete事件,Application被SystemManager添加到显示列表后触发,完成度比createComplete更高,在这个事件中可以访问舞台。

初始化事件

初始化事件都是FlexEvent事件,对应类型如下表:

事件名称

事件类型

preinitilize

FlexEvent.PREINITIALIZE

initilize

FlexEvent.INITIALIZE

creationComplete

FlexEvent.CREATION_COMPLETE

applicationComplete

FlexEvent.APPLICATION_COMPLETE

 

Flex框架中的引用

在Flex在框架下,虽然也可以通过显示列表引用容器,文档类等对象,但在Flex框架中SystemManager和Application有着特殊的意义,通过Flex提供的引用方式比root这样的引用更加标准。

引用SystemManager

SystemManager作为Flex发布swf文件的文档类,使用UIComponent的systemManager:ISystemManager属性引用比使用root引用更加标准,ISystemManager类型提供更好的兼容性,因为air程序的窗口也用到这个接口,systemManager属性只有调用addChild()方法将组件添加到显示列表后才被赋予不要在组件的构造函数中访问systemManager。你也可以通过SystemManager提供的静态方法SystemManager.getSWFRoot(object:Object):DisplayObject获取对象所属的SystemManager。

引用Application

UIComponent的parentApplication:Object属性引用该组建所属的Application对象,如果项目被载入,组件的parentApplication属性指向原有的Application对象,加载swf包含的Application对象的parentApplication属性指向加载器的Application对象,如果swf没有被载入,parentApplication为null。Application.application:Object引用顶级application对象。

引用文档顶级容器

UIComponent的document:ObjectparentDocument:Object属性引用组件所属的mxml或as文件顶级容器,如果mxml或as文件不包含顶级容器,则顶级容器为加载器的顶级容器。顶级容器的document指向自身,parentDocument指向加载器的顶级容器。例如使用mxml创建基于Panel的自定义组件MyPanel,MyPanel中子容器的document和parentDocument都指向MyPanel,Mypanel的document指向自身,parentDocument指向Application,如果MyPanel不是一个容器而是一个Button,则MyPanel的document和parentDocument都指向Application。

引用所有者

UIComponent的owner:DisplayObjectContainer属性表示子组件的所有者,owner可以由我们自行设定,默认为组件的父级,通过owner能够跨越多个父级从而简化了逻辑。

内联定义中的引用

内联一般用于列表组件的单元渲染器,内联能够通过一个mxml文件中生成多个类,因此使用内联中的定义并不在mxml运行环境中,要引用内联所属的mxml环境,需要借助outerDocument:Object属性引用Application实例。outerDocument不是UIComponent的属性,只能在内联定义中使用。

Flex引用的优点

通过上面的学习可以看出Flex提供的引用方式跨越了显示列表,为在Flex框架下工作提供了方便,我们几乎可以在任意地方访问Application和SystemManager这两个重要的对象,有了Application和SystemManager对象便可以引用swf中的任何公开对象和定义,Application和SystemManager也能互相访问,只要知道一个就可以得到所有。

顶级容器不能设置id属性,document属性成了访问根容器的常用方式,无论在自定义组件或Application中都适用。在项目规划中,为了追求封装,不建议在自定义组件或模块中引用父级对象,因此parentDocument和parentApplication用的并不多。在内联编程方式中,不必通过parent攀升来寻找内联所在的运行环境,通过parentDocument是访问所在运行环境的快速方式。


posted on 2012-03-11 21:58  星^_^風  阅读(241)  评论(0编辑  收藏  举报