On 4/15/16, 10:09 AM, "omup...@gmail.com on behalf of OmPrakash Muppirala" <omup...@gmail.com on behalf of bigosma...@gmail.com> wrote: >> >> FWIW, overuse of visible and includeInLayout together has been one of >>the >> most common performance killer I've seen in large applications. > >What would be the best way to hide the object and not let it take up space >in the layout?
States with includeIn/excludeFrom One of the fundamental principles of FlexJS is pay-as-you-go, or "just-in-time" instead of "just-in-case". Yes, there is a bit more work to be done to do "just-in-time" and when doing rapid prototypes I will occasionally use visible and includeInLayout, but if you think about it, when you use those two properties together you are essentially creating instances of display objects just in case they are needed later. Switching to use includeIn/excludeFrom is usually straightforward unless you have a lot of complex conditions under which you want these widgets to appear and disappear. But the real work that often gets people is that your application code can no longer assume that widget instances exist at, for example "creationComplete" event time. But, IMO, that means you have written your code in a "push-down" approach instead of a "pull-down" approach, and "push-down" is also just-in-case coding, and does not lend itself to future encapsulations like modules. Unfortunately, "push-down" is very tempting because it is centralized, and some 3rd-party libraries that handled i18n and IoC invited folks to write push-down code. But essentially you pay for it at startup time. For example, here is (most of) a "push-down" app. <application creationComplete="setup()"> <fx:Script> function setup() { if (Capabilities.language == "en_US") { intro.text = "Introduction"; login.message.text = "Please log in"; } } </fx:Script> <s:Label id="intro" /> <local:LoginDialog id="login" visible="false" includeInLayout="false" /> </application> Here is the same app with states and "pull-down" code. <application> <fx:Script> function setupLabel() { if (Capabilities.language == "en_US") intro.text = "Introduction"; } function setupDialog() { if (Capabilities.language == "en_US") login.message.text = "Introduction"; } </fx:Script> <s:states> <s:State name="normal" /> <s:State name="login" /> </s:states> <s:Label id="Intro" creationComplete="setupLabel()"/> <local:LoginDialog id="login" includeIn="login" creationComplete="setupDialog()" /> </application> What isn't shown in the apps are logic that checks to see if you already have a valid session token and skips the login dialog. In the scenario where you have a valid session token, you can see that in the push-down app, the LoginDialog will be instantiated and have properties set on it for no benefit at all. It just wastes cycles. If it takes 100ms to do that and you have 10 other scenarios like that, you've wasted a full second. And I saw about 50 in one app I was profiling for an enterprise customer. And note that the setup() method assumes that the login exists at creationComplete time and you will get an exception if you just switch to using includeIn/excludeFrom. In the pull-down app, more code does get run if the login dialog has to show up, but if it doesn't much less code gets run. Further, if you decide later to move the LoginDialog to a module and not even load its code in the main SWF, you can move it out along with its method in the Script block more easily. That's just better encapsulation, IMO. In FlexJS, I am trying really hard not to write push-down code in the framework. The Spark port will have to have all of the old Flex code paths, so that will be an exception, but in general, we should all think about pay-as-you-go and just-in-time when writing our apps, even if it does take more work. Of course, this is just my opinion. I could be wrong ;-) -Alex