理解Flex3的组件和框架的生命周期(三)
作者:李学锟 类型:编译 来源:Flex爱好者专栏
理解Flex3的组件和框架的生命周期(二)
理解Flex3的组件和框架的生命周期(三)
理解Flex3的组件和框架的生命周期(四)
一个Flex应用程序的诞生
我们已经对组件的生命周期有了一个很好的理解,现在我们来看一下Flex应用程序的生命周期。Flex应用程序的生命周期和组件的生命周期很相似,但有一些非常重要的补充和修改,以提供一个支持管理完整的系统。我们将应用程序的生命周期分为:构造,初始化,预加载,创建子类,显示子类和销毁。
Flex应用程序阶段:构造阶段
Flex应用程序的构造阶段要比组件的构造阶段有一点深入,因为它是在编译好的SWF装载后,在任何类的实际构造之前开始的。
当一个SWF已装载入播放器时,SWF的第一帧已做好了准备,接着就开始执行。Flash Player的最强大的特点之一就是不需要把所有的内容都加载完才开始执行。播放器主要的职责是流媒体的内容和对已加载的进行执行。这种能力保证了较大的SWF的文件在播放内容的同时加载余下的部分。
Flex编译器的黑暗艺术
从我们目前的研究来看,第一个Flex框架的代码片断是关于SystemManager的创建和执行部分。至于SystemManager是如何与SWF连接和定义,并作为第一个类被创建和执行的,这些问题在目前有效的文档里并没有明确的描述。我们只知道Flex 编译器在它生成和输入SWF文件时定义了这个连接,并定义了应用程序的SystemManger类作为SWF根部的MovieClip类,这就告诉了Flash Player在加载时构造SystemManger实例。
不幸的是,关于Flex编辑器的实际过程和它是如何创建最初的帧栈的问题,有点超出了本文所讨论的话题。有希望的是,随着我们研究的深入,有可能更新本节的内容并给编译器关于创建第一帧的堆栈更详细的解释。目前为止,我们尽可能地解释清楚。所以现在,耐心与我们从SystemManager构造开始。
首要位置的SystemManager
每一个Flex应用程序(RIA或AIR)都有一个SystemManager实例来负责管理应用程序窗口的所有显示内容。SystemManager ASDoc 注释中是这样描述应用程序窗口的:应用程序中用来显示的一片可视的区域。它可以是操作系统的一个窗口或浏览器的一个区域。
这就表明一个SystemManager对应所有的窗口。当SystemManager被创建,它首先检查自己是否是当前窗口的第1个SystemManager。在本文中我们假定所创建的是第1个SystemManager,并且我们不研究子类的SystemManager和子系统之间如何管理的。
这个SystemManager是否是当前的应用程序窗口默认的SystemManger取决于,stage属性是否定义在构造方法中。
一个stage是所有显示对象的基类,包括SystemManager。正如Highlander,每个应用程序窗口只能有一个stage。第1个挂在stage上的DisplayObject是根对象,并且这个DisplayObject的root属性设置为本身。其它所有的显示对象都挂在根对象上,并将它们的root属性指引到根对象上。如下图,应用窗口的层级显示出它们的结构是如何组织的。
当一个DisplayObject被添加到舞台上,它的stage属性被定义并指向当前应用程序的stage。只有根DisplayObject的stage属性设置在构造方法中,其它显示对象的stage属性在该对象被添加到显示堆栈(如addChild(),Loader,等)时设置。所以当继承了MovieClip->DisplayObject的SystemManager在构造阶段,先检查stage属性是否已定义。
一旦SystemManager确定了它的root属性,它有权力来访问自身的loaderInfo属性。这个loaderInfo属性含有LoaderInfo类的对象,LoaderInfo类允许访问信息,比如源SWF的url,传给SWF的参数,域信息,内容,已下载的字节,总字节,等。
在典型的Flash/Flex开发中,当加载应用程序内容时,我们通常访问SWFLoader的loaderInfo详细的信息或其它以Loader为基类的信息。当应用程序正在加载目标内容时,利用loadInfo对象作为取得当前加载的信息。在这种情况下,SystemManager不会作为应用程序的子类去加载;它会被Flash Player自身去加载。根DisplayObject的是指引到Flash Player的loaderInfo对象,因此,我们基本上可以观看我们自己的SWF加载。
LoaderInfo 类其中一个特点就是派发Event.INIT事件,当被加载的SWF的所有属性和方法都可被访问,第1帧的子类对象已构造和所有第1帧的ActionScript代码执行完后,该事件才会派发。这是很重要的,因为SystemManager注册自身的loaderIfno属性,侦听Event.INIT事件的派发。当该事件被派发后,SystemManager就会知道初始化所使用到的重要信息和其它的配置信息已经加载完毕并可以使用了。
Flex 应用程序的阶段:初始化
一旦SystemManager的Event.INIT事件派发后,SysttemManger就开始应用程序的初始化阶段。SystemManager首先要做的是检查它的父类,看自己是否是根,注册Event.ENTER_FRAME事件(当每个新的Flash帧开始时派发),然后调用自己的initialization()方法。
在initialization()方法里,SystemManager设置自身的宽度和高度来封装应用的尺寸,然后创建Preloader类的实例。在我们开始创建应用程序之前,需要加载所有必要的辅助库和资源库来确保程序的功能。
外部资源管理
Flex3一个强大的特点就是使用远程共享库(RSL)r的外部资源管理和本地资源管理。为什么要使用外部的内容,有很多理由,比如说,下载字节的大小,共享资源,目标语言等。
这种技术的一个风险就是当程序需要它们时,要确保它们的已被加载并是可用的。所需的外部内容是委托给SystemManager,它使用Preloader来加载内容并把反馈信息显示给用户。
一旦SystemManager创建Preloader,它就注册Preloader的FlexEvent.INIT_PROGRESS事件和FlexEvent.PRELOADER_DOWN事件,当所需的外部资源所加载完成后就开始Application类的构造-初始化阶段。接着,Preloader实例对象作为子类添加到SystemManager上,但此时数据还没有开始加载。
SystemManager在使用Preloader开始加载内容之前,首先需要创建一个所需资源的列表。Preloader的第1个外部内容列表是RSL列表,它是应用程序所需要的。RSLs列表提供了一个info()方法来供外部访问,info()这个方法是编译器来完成的。
一旦RSLs列表定义完成后,SystemManger创建ResourceManager的实例化对象来提供Preloader来访问已编译的资源包。一个默认的资源包通常是编译在应用程序里的,Preloader可用使用它给用户显示本地的信息,或当应用程序在运行时报错时,能够显示本地语言的错误提示信息。若系统在编译时没有把资源包加入的话,它不会显示本地化的信息,因为Preloader没有加载额外的资源。
该SystemManager建立了基础的StyleManager使Preloader可以使用它,然后SystemManager解析任何通过SWF的flash vars的变量,以确定用该应用程序
使哪些区域设置。接下来,SystemManager建立外部资源列表通过定义在flash vars里的URL来加载,确定是否显示一个自定义的Preloader界面(编译器通过info()方法),然后Preloader开始传递外部资源列表里的资源来加载,显示类用来渲染Preloader。
Flex 应用程序:预加载
Preloader 采用外部资源列表,创建RSLListLoader的实例,并开始加载内容。随着RSLs和资源绑定的加载,进度事件被派发并通知Preloader来更新显示的进度条。一旦Preloader加载所有的RSLs,它将派发FlexEvent.INIT_PROGRESS事件来通知SystemManager表示所有所需要的外部资源已加载完。
Preloader负责处理两个主要的任务,首先是加载RSLs和资源绑定(就是刚才讨论的),另外的职责就是Flex应用程序在子类创建和子类显示阶段反馈给用户。随着我们进入更深的过程,将讨论Preloader完成任务后它什么时候会更新。
现在RSLs和包加载完,引起Preloader派发INIT_PROGRESS事件,SystemManager接受到这个事件后,通过nextFrame()方法前进一帧。在初始化阶段SystemManager为自己注册了ENTER_FRAME事件,该事件引发docFrameHandeler()方法。当我们调用nextFrame()方法时,SystemManager进入一帧并派发一个ENTER_FRAME事件。
docFrameHandler()方法开始定义许多单例的类在整个应用程序中,例如:BrowserManager,HistoryManager,CursorManager,LayoutManager等。一旦单例类被定义后,加载编译的资源,然后为应用程序设置ResourceManager的实例,使它们的内容在整个系统中可用。
Flex应用程序阶段:子类的创建
至此,我们已经获得外部资源的加载和系统准备,我们开始创建根类Application。所有这些信息对我们来说必须是可用的,因为它定义了框架和实现运行程序所需要的。现在,我们加载了所有信息,并在适当的时候开始创建顶级别的Application类。为开始创建顶级别的Application类,docFrameHandler()方法调用SystemManager的initializeTopLevelWindow()方法,它启动创建的过程。
首先,SystemManager为窗口注册MouseEvent.MOUSE_DOWN事件来处理焦点管理;注册stage的Event.RESIZE事件,当用户改变窗口的大小时,SystemManager为触发该事件,并将它传递给它的子类。这些注册信息完成后,Application实例已创建。
该类是为根Application所创建,根Appliation是在编译的过程中所定义。它可能是你扩展了Application类的实例或在AIR工程中扩展了WindowedApplication的实例。SystemManager利用工厂的方法调用create(),该方法info()["mainClassName"]参数决定什么样的类型去创建。
现在我们创建了Application的实例,SystemManager注册该实例的FlexEvent.CREATEION_COMPLETE事件,定义url和参数;然后更新Apllication和SystemManager的宽度和高度。
在Application更新完size后,SystemManager用Preloader注册Application实例。Application注册到Preloader,确保了Preloader注册不同生命周期生效阶段的事件("validatePropertiesComplete","validateSizeComplete",
CREATION_COMPLETE事件,等)。Preloader注册这些事件可以给用户提供Application的组件成长阶段的进度。
Flex 应用程序阶段:子类显示
因Application类继承了UIComponent,所以它必须遵循组件的生命周期。此时,Application已完成构造阶段,但并没有开始添加阶段,直到将它自己添加到父组件,如SystemManager。
如果SystemManager刚调用过addChild()方法并经过了三个子步骤(addingChild(),$addChild()和childAdded()),Flash Player将开始渲染Application的内容到屏幕上。尽管Application子类的创建过程已完成和运行了所有初始化的代码,也得花费许多时间和帧来得到最终的Application。
许多工作是否需要屏幕重绘,决定于Application它初始化和第一个失效-生效阶段的完成。阻止没有必须的重绘,SystemManager只调用处于在出生和生成阶段的组件的addingChild()和childAdded()方法。
在Appliction派发CREATION_COMPLETE事件后,SystemManager发送Application 通过多个失效的验证。Preloader还侦听了Application的CREATION_COMPLETE事件,然后派发PRELOADER_DOWN事件给SystemManager。
这时,SystemManager将要移除Preloader对象,因为它已完成了UI的任务。一旦SystemManager移除Preloader对象,将使用super.addChild()方法来添加Application对象;这时SytemManager和Application都会派发FlexEvent.APPLICATION_COMPLETE事件。
现在,应用程序启动,SystemManager自动降级到跟踪系统,并运行跟踪系统的鼠标事件,光标管理,对话管理和其他SystemManager职责。应用程序进入了更新阶段,这个阶段一直进行,直到用户关闭或退出系统。
Flex应用程序阶段:销毁
Flex应用程序的销毁阶段真正依赖于它是如何执行的。基于浏览器的程序,销毁阶段是很短暂的,并且没有任何通知;也就是说,应用程序在这一阶段你是没办法控制的。这也意味着,操作的确切顺序是很难弄清楚的。我们只是说当用户关闭了浏览器,它结束了SWF实例的进程。在这时,单纯地用ActionScript是没有什么可以控制的。
在基于AIR的应用程序中,使用WindowedApplication类可以有更多较好控制。AIR提供了关闭事件的多种处理者,你可以优雅地退出系统或阻止关闭系统。同样地,确切地操作顺序还是无从知晓,因为NativeWindow和NativeApplication都包含在playerglobal.swc里,我们不能访问它们的代码近一步地分析。
- 上一篇:
- 3ds MAX教程:创建荒漠中废弃的房屋
- 下一篇:
- 理解Flex3的组件和框架的生命周期(四
- 相关教材
- 理解Flex3的组件和框架的生命周期(四
- 最近更新
