Deferred creation of ViewStack children
Сен 16
Задача: ускорить процесс запуска приложения, путем создания только нужных контейнеров в multiview контейнерах (ViewStack, TabNavigator, Accordion).
По-умолчанию creationPolicy="auto", но иногда хочется поставить им вообще "none" и взять под свой контроль процесс создания чилдов.
Решение: создавать дочерние контейнеры из их декспритора.
Код:
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
creationComplete="{bBar.selectedIndex = -1}">
<mx:Script>
<![CDATA[
import mx.core.UIComponentDescriptor;
import mx.formatters.SwitchSymbolFormatter;
import mx.events.ItemClickEvent;
import mx.controls.Alert;
public var c : int = 0;
private function println (str : String) : void
{
output.text += String(c++) + ": " + str + "\n";
}
private function onItemClick (event : ItemClickEvent) : void
{
var childDescriptor : UIComponentDescriptor = vstack.childDescriptors[event.index];
var selectedChild : * = vstack.getChildByName(childDescriptor.id);
if (selectedChild == null)
{
selectedChild = vstack.createComponentFromDescriptor(childDescriptor, false);
vstack.selectedChild = selectedChild;
vstack.validateNow();
}
else
{
vstack.selectedChild = selectedChild;
}
}
]]>
</mx:Script>
<mx:ToggleButtonBar
id="bBar"
itemClick="onItemClick(event)">
<mx:dataProvider>
<mx:String>Canvas 1</mx:String>
<mx:String>Canvas 2</mx:String>
<mx:String>Canvas 3</mx:String>
</mx:dataProvider>
</mx:ToggleButtonBar>
<mx:ViewStack
id="vstack"
width="400"
height="250"
creationPolicy="none">
<mx:Canvas
id="c1"
label="Canvas 1"
backgroundColor="#CC9955"
initialize="println('canvas 1 inited')"
creationComplete="println('canvas 1 created')"
show="println('Show Canvas #1')">
<mx:Label
text="Canvas #1" />
<mx:Button
id="b1"
top="20"
label="button 1" />
</mx:Canvas>
<mx:Canvas
id="c2"
label="Canvas 2"
backgroundColor="#99CC55"
initialize="println('canvas 2 inited')"
creationComplete="println('canvas 2 created')"
show="println('Show Canvas #2');">
<mx:Label
text="Canvas #2" />
<mx:Button
id="b2"
top="20"
label="button 2" />
</mx:Canvas>
<mx:Canvas
id="c3"
label="Canvas 3"
backgroundColor="#9955CC"
initialize="println('canvas 3 inited')"
creationComplete="println('canvas 3 created')"
show="println('Show Canvas #3')">
<mx:Label
text="Canvas #3" />
<mx:Button
id="b3"
top="20"
label="button 3" />
</mx:Canvas>
</mx:ViewStack>
<mx:TextArea
id="output"
width="400"
height="250"
editable="false" />
</mx:Application>
Можно заметить, что самый первый показанный контейнер не диспатчит ивент show - так работает ViewStack…
О creationPolicy (none, auto, all, queued): LiveDocs: About the creationPolicy property
Во Флексе есть два вида контейнеров: singleview и multiview.
Для multiview:
- none - не создававть ничего;
- all - создать все чилды (и их чилды рекурсивно). очень жестко;
- auto - создать только первоначальный контейнер (и его чилды), т.е. тот что указан в selectedIndex/selectedChild или самый первый если не указано. остальные контейнеры будут инстатиированы но не инициированы, при этом их чилды не будут созданы, естественно события initialize и creationComplete не опубликуются.
Для singleview контейнера (VBox, HBox, Canvas) значение all/auto и none - соответственно создавать автоматически чилды (и чилды их чилдов - рекурсивно) или нет. В данном случае all и auto равнозначны. Значение queued - позволяет управлять очередностью создания с помощью тега creationIndex. Вот небольшой пример для иллюстрации:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Panel
creationPolicy="queued"
initialize="{trace('panel 1 inited')}"
creationComplete="{trace('panel 1 created')}">
<mx:Button
label="Button 1.1"
initialize="{trace('button 1.1 inited')}"
creationComplete="{trace('button 1.1 created')}"/>
<mx:Button
label="Button 1.2"
initialize="{trace('button 1.2 inited')}"
creationComplete="{trace('button 1.2 created')}" />
</mx:Panel>
<mx:Panel
creationPolicy="queued"
creationIndex="0"
initialize="{trace('panel 2 inited')}"
creationComplete="{trace('panel 2 created')}">
<mx:Button
label="Button 2.1"
initialize="{trace('button 2.1 inited')}"
creationComplete="{trace('button 2.1 created')}"/>
<mx:Button
label="Button 2.2"
initialize="{trace('button 2.2 inited')}"
creationComplete="{trace('button 2.2 created')}" />
</mx:Panel>
<mx:Panel
creationPolicy="queued"
initialize="{trace('panel 3 inited')}"
creationComplete="{trace('panel 3 created')}">
<mx:Button
label="Button 3.1"
initialize="{trace('button 3.1 inited')}"
creationComplete="{trace('button 3.1 created')}" />
<mx:Button
label="Button 3.2"
initialize="{trace('button 3.2 inited')}"
creationComplete="{trace('button 3.2 created')}" />
</mx:Panel>
</mx:Application>
Вывод программы:
button 2.1 inited
button 2.2 inited
panel 2 inited
button 2.1 created
button 2.2 created
panel 2 created
button 1.1 inited
button 1.2 inited
panel 1 inited
button 1.1 created
button 1.2 created
panel 1 created
button 3.1 inited
button 3.2 inited
panel 3 inited
button 3.1 created
button 3.2 created
panel 3 created