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

Reply via email to