Mar 24 2009
Improving Perceived Layout Performance in Flex
The Problem
For a typical browser-based Flex application, as the brower is resized by the end user, it’s very common to see the Flex content lag behind the browser frame. As the Flex app is resized very often you can see the Stage background paint, before the Application background can catchup.
Take the following example SWF (click to open):

After launching the sample, resize the browser frame quickly left and right, and up and down from the bottom right corner of the browser chrome. You’ll notice that along the right and bottom edge of the viewport, the green stage background can be seen, as the content tries to keep up with the resize events. This “lag” is most commonly seen on Mac OSX 10.4 and later when running in the standalone Flash 10 player, Safari, or Firefox. On Windows, the lag is most commonly seen within the Firefox browser, but depending on your hardware configuration, can also occur in IE, AIR, and the standalone player.
The Solution
Whenever the player Stage is resized, the Stage issues a ‘resize’ event. In Flex, our top level Application object listens for the resize event. When it’s received Flex invalidates the display list, then queues up a layout request. Only later, when we eventually receive a ‘render’ event from the Stage, or an ‘enterFrame’ do we actually layout and update our display list.
Flash delivers stage resize events pretty much in lock step with the browser or parent container, but render and enterFrame events are tied to the player’s natural update interval. Since Flex waits until the following update interval to actually paint, we’ll always see this lag.
In the sample above, I’ve added a checkbox, which when enabled, demonstrates a smoother resize approach. Essentially we just ensure that we ‘validate’ our display list upon receipt of every Stage resize event. The solution is to ensure that when our root application is resized, that we follow suit with a validation (layout) as soon as we can, rather than deferring as is the typical case when child elements are resized on their own. Perceived performance can be greatly enhanced.
The Catch
Why don’t we make this change within the core SDK itself? Unfortunately, there’s a catch - an existing player bug we would have to work around, primarily on Windows. When the plug-in version of the player has its WMODE rendering mode set to “transparent”, or any other non-default value for that matter, display list corruption with TextFields can occur (specifically those using system text). When WMODE is set to transparent for example, and TextFields are present in the display tree, the raster representation of these text elements becomes visibly corrupt when they are moved and updated within a Stage resize event handler. A player bug is logged and the issue is being addressed.
In the mean time, if you know your interactive will never be using a non-standard WMODE, feel free to take the approach outlined. The results will be a much smoother, more responsive layout experience in most cases. Some cookbook code follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" applicationComplete="appComplete();"> <mx:Script> <![CDATA[ private function appComplete():void { stage.addEventListener(Event.RESIZE, onStageResize); } private function onStageResize(e:Event):void { validateNow(); } ]]> </mx:Script> </mx:Application> |
Thank you!
Hey,
very nice example, I am building a Flex app as my graduation thesis, and I have Event.RESIZE that changes and updates layout of my app. The lag was not something that I was all that worried about, but still your solution is a added benefit for my app, and it responds so snappier.
Thanx again.
Ladislav
p.s. will add your blog to my blogroll