`
bal1212
  • 浏览: 76013 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Building monolithic Flex SWFs that still startup quickly

阅读更多

Building monolithic Flex SWFs that still startup quickly

Monolithic Flex SWFs that still startup quickly? Doesn't that sound weird? Of course it does, but actually it works just fine. Thanks to the way the Flash Player downloads multi-frame SWF files it's possible to defer the loading of "heavy" parts of your Flex application making the startup time pretty fast - under the hood the Flash Player still streams in the remaining data (BWT, with "streaming" I'm not referring to live video streaming or anything video releated, there's an ongoing discussion about this somewhere else)

p>Although this behaviour is common knowledge to most Flash developers it's probably not to the typical Flex developer as all frame- and timeline-based business is properly hidden by the Flex framework. By default, a Flex application actually is a 2 frame SWF file. Frame 1 contains the bootstrapping code to create the Flex application and the preloader and frame 2 contains all classes of the application itself. After frame 1 is fully loaded the preloader is displayed as long as frame 2 is downloading (this results in the typical loading screen of a Flex application). Once the whole SWF is downloaded into the Flash Player, the Application class gets instantiated and displayed. Now, the typical situation is that this 2 frame SWF file gets bigger and bigger as your application gets more and more complex, thus the download size and therefore the application startup time increases. A typical refactoring is to partition the application into multiple smaller SWF files ("Modules") and load these Modules SWF files on demand at runtime - which introduces other issues like class linking optimizations etc.

Interestingly (and this is what this post is all about), it's possible to create Flex SWF files made up of more than these 2 frames. A nice side effect of this approach is that the SWF continues to download after the Application class has been created. This means the user can already interact with the Flex application while behind the curtain additional classes and assets gets pulled in. Or as noted in the Flex Developers Guide PDF on page 201: "The advantage to doing this is that the application starts faster than it would have if the assets had been included in the code, but does not require moving the assets to an external SWF file".

There's not too much documentation available on how to implement this in detail, however. The best available material on what really happens are this blog post by Roger Gonzalez (former Adobe employee who worked on the Flex compiler) and a Powerpoint presentation on Modules by Alex Harui (Adobe employee, Flex Team). On the last two pages of Alex' great presentation he mentions what would be possible if Modules (i.e. compilation units) would be added behind frame 2 in a Flex SWF file. Adding those additional frames to a SWF file can be achieved by using the mxmlc -frame compiler argument specifying a label/identifier for the frame and one or more classes that should be linked to the frame. At runtime this ensures that the class/classes do not get loaded before the previous frame is completely loaded - and tada: there you have your streaming Flex application :)

Here are the implementation details for a quick and dirty test case (Btw, while not necessary I added support for the Module API so this plays nicely with the mx.modules.ModuleManager class):

First, I created a simple plain Flex 2 Application. Next, a class called TestFactory which implements mx.core.IFlexModuleFactory was created. This class will later be used to create instances of a Module called Test. The TestFactory class also implements a public static function frame(value:Object):void which is needed later.

To link the TestFactory class onto an additional frame "outside" the default 2 frame section you'll have to add something like

   -frame test TestFactory 
 
to the mxmlc arguments (either in Flex Builder or on the command line). This creates the 3 frame SWF file.

At runtime when frame 3 is hit, the static frame() method on the TestFactory class is called (this is not documented anywhere) passing in an instance of the active SystemManager implementation. Inside this method you can then register the TestFactory on the ModuleManager:

   ModuleManager.getModule("published://myTest").publish(new TestFactory());
 
Note: Although in the documentation it says to use an URL starting with publish:// it actually has to be published://. After the Module is published you can call
   ModuleManager.getModule("published://myTest");
 
from withinh the application to get a reference to the TestFactory instance and call create() on it to create an instance of whatever is created by the factory class.

The neat thing is that this really gets streamed in while the SWF is downloading but after the creationComplete Event has been dispatched - in other words: your application is already up and running while in the background the SWF still streams in. I added another class on frame 4 which makes the SWF pretty heavy (the class on frame 4 simply embeds a 8 MB mp3 file) to see if the Application really gets started before everything is in place - and it worked exactly as expected. Very nice!

So in the end you may ask why to put everything into one monolithic SWF file at all when it seems much more elegant to load additional Modules as external SWF files. Of course, this may reduce total download size as it only loads a Module SWF when explicitely requested. This is especially true if your application is really consisting of many "mini apps" and chances are high that not every SWF needs to be loaded at all. If that's the case you should probably stay with Module SWFs. On the other hand, if you're application is not that partitioned and you just need better startup performance then the approach described above may be the perfect match.

Dirk.

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics