I'm having some troubles with Flex with regards to changing controls on different viewstack panels. At runtime, certain controls aren't accessible and come back as null. Here's an example structure:
viewstack1
canvasPeople
datagridPeople
canvasDetails
tabNavigator1
canvasPersonDetail
txtLastname
canvasPersonOptions
comboboxOccupation
I have a "click" handler in datagrid1 set up to activate canvasB (viewstack1.selectedChild = canvasB) and the detail options box (tabNavigator1.selectedChild = canvasPersonOptions). The former works OK but the latter returns an error about accessing a null object, because at the moment the user clicks on an item in the People datagrid, the tabNavigator1 is null, as is any control underneath it. (its parent, though (canvasDetails), is addressable.) Currently this is a tiny application, so it's not like it's waiting to load the items. Is there a way to control how Flex renders controls so they're accessible before the user sees them? I don't know if this is specific to the viewStack control.
Yes, this is referred to as "creation policy" and it's a property on all Container classes. To do what you we're looking for, you can use a creation policy of "all"; "auto" is the default.
A creationPolicy of ContainerCreationPolicy.AUTO means that the container delays creating some or all descendants until they are needed, a process which is known as deferred instantiation. This policy produces the best startup time because fewer UIComponents are created initially. However, this introduces navigation delays when a user navigates to other parts of the application for the first time. Navigator containers such as Accordion, TabNavigator, and ViewStack implement the ContainerCreationPolicy.AUTO policy by creating all their children immediately, but wait to create the deeper descendants of a child until it becomes the selected child of the navigator container.
A creationPolicy of ContainerCreationPolicy.ALL means that the navigator containers immediately create deeper descendants for each child, rather than waiting until that child is selected. For single-view containers such as a VBox container, there is no difference between the ContainerCreationPolicy.AUTO and ContainerCreationPolicy.ALL policies.
More info here:
http://livedocs.adobe.com/flex/3/html/layoutperformance_04.html
Be careful with this though: Flex picked AUTO as the default for a reason. If your app grows large, the initialization time under creationPolicy=all will be large.
The creation of subcomponents is controlled by the creationPolicy property. It is described in detail in the Flex 3 documentation page "About the creationPolicy property".
If you set the property to "all", every subcomponent of the ViewStack container will be created as soon as the ViewStack is created. The same works for the TabNavigator. Of course this might have some performance implications, which are also described in the documentation.
Related
I'm puzzled about whether the visible property of DisplayObject is:
an indication from Flex of whether the display object is visible.
an instruction to Flex to display the display object.
I'm asking because I'm automating some Flex tests using Flex Pilot, and I need to know for certain when a display object becomes clickable. In the application I'm testing, clickable seems to mean rendered.
Given the nature of the application and my tests, I don't think it's feasible to watch for the updateCompleted event. I need a way to detect whether the display object is visible based on the values of its properties and its containers' properties at a given moment.
I understand that even if a display object's visible property is true, it will be visible only if all of its containers are also visible. This means that I'll have to extend Flex Pilot by writing an ActionScript method to determine whether the display object and its containers all have visible=true. But I'm concerned that even that method won't tell me for sure that the display object is really rendered, and therefore clickable.
My puzzle comes from reading two descriptions from Adobe.
The "About creating advanced components" document suggests that the visible property is set by Flex after the display object is rendered. In this description, it is Flex's job to set the value,
so that value is thus an indication from Flex of whether the display object is visible.
On the other hand,
Adobe's description of the visible property suggests that the property is writable. And the code sample suggests that if the application changes the value, Flex will respond by displaying or hiding the display object. In this description, the application sets the value as an instruction to Flex to display the object. I'm guessing that in this case Flex re-renders the display object (if visible changes from false to true) or its container (if visible changes from true to false).
So two main questions:
Is the visible property used in both of these ways, both as an indication from Flex about the display object's visibility and an instruction to Flex about whether to display the object?
If the application changes visible from false to true, when does the display object actually become visible? Is it visible by the time the setter returns? Or does setting the property merely schedule the object to become visible during some later event? If it's the latter, that means there may be a duration during which visible is true, but the display object has not yet been rendered. If that's the case, I'm at a loss for how to determine, from the state of the display objects at a given instant, whether a display object has been rendered.
There are some key constraints for a DisplayObject to be rendered. First of all, it has to be in the display list. visible has to be set to true, otherwise it would be ignored from the rendering. The last key aspect is the so called elastic race track which basically describes when event handling, code execution and rendering occur. So, implementing event handlers for FlexEvent.UPDATE_COMPLETE is not so wrong, because those are dispatched when ever a property changes, which change the rendered representation of the component on the screen.
Is the visible property used in both of these ways, both as an indication from Flex about the display object's visibility and an instruction to Flex about whether to display the object?
Yes, the visible property is initially set to true by the framework before FlexEvent.CREATION_COMPLETE is dispatched, so the Flash player won't draw the component in a state (i don't mean the Flex view states), which is some where between construction and having the complete initialized view.
If the application changes visible from false to true, when does the display object actually become visible? After the next render cycle happend.
I have created a custom item renderer for the tree, i have added some children in create children function, my problem is that sometimes i need to show these children and sometimes i don't, depending on clicking on a button which also i have added at create children, the problem is that i had to create the item even if i don't want it to be visible, and removed it by making visible false, and this costs a lot of memory, i have tried to create it at buttons click listener but when scrolling the child disappears, and it may appear again if i keep scrolling up and down..
i am trying to add the child just when i need it to be visible, is this possible or i have to create it on child creation method?
Typically you do something like this with states. This way the components within the container (in this case your item renderer) are only created when the container enters the given state. The nice thing about taking this approach is that you can remain oblivious to when components need to be created/removed and let the states model handle that for you. Hope that helps.
I have two mxml files. one is main that is application tag mxml file and another is my mxml component file.
I have a viewstack in my main mxml whose id is, say, "mainViewStack".
Now I want to set selectedChild property of "mainViewStack" from my mxml component file.
But I m getting error:
Error #1009: Cannot access a property or method of a null object reference.
on accessing mainObj.mainViewStack.selectedChild.id where mainObj is the object of main mxml file.
Please help me out.
Thank u.
My guess is that you're trying to access the child before it's created. But that's hard to tell without the code.
Try waiting until the FlexEvent.CREATION_COMPLETE event on the application to access the selected child.
This issue is referred to as "deferred instantiation" and is a product of the Flex Component Lifecycle. If you want an extremely thorough explanation of this concept, this white paper is probably the best I have read.
Essentially Flex creates components as they are needed. Each component has a lifecycle that takes it through stages:
Construction
Addition
Initialization
Invalidation
Validation
Update
Removal
A sub-component isn't going to be accessible until it has passed through the initialization phase. This is the point at which a Flex component will dispatch its CREATION_COMPLETE event, letting you (and the framework) know that it is ready for interaction. Prior to this event, you are going to receive null reference errors when attempting to access the component or its children.
ViewStacks compound this by default by not initializing sub-components until they are called for display. The creationPolicy property of a ViewStack, by default, is set to auto. There are several options for this property, including all. Be aware, however, that this can potentially present severe performance issues, as all of the components inside the stack are going to be initialized immediately regardless of whether or not the user actually even looks at the component.
In your specific case this isn't the problem. The component that contains the view stack hasn't been completely initialized. You need to set the child of the ViewStack in a CREATION_COMPLETE event handler.
or you can give "creationPolicy=all" because Flex only creates the first visible child from the viewstack
You can use this code in your MXML component to change application's ViewStack selected child from other MXML component. However it is not a good practice.
FlexGlobals.topLevelApplication.mainViewStack.selectedChild = FlexGlobals.topLevelApplication.childId
You can use static event dispatcher to dispatch an event from one view and listen that event in an other view.
How can I make sure all the components, even those that are not going to be visible at the beginning, load right away when I start my application?
I have an application with a ViewStack whose visible child is set via a sidebar menu. Say the ViewStack has two children, A and B. A is initially visible, whereas B is not. How can I make sure they both load at the beginning, so that when I change to B I don't have to wait for it to load?
each of your viewstacks should have
creationPolicy = "all";
not sure if this can be set at the application level or not to control all children, but I know it works on viewstacks.
I seem to be running into an issue (Cannot access a property or method of a null object reference) binding events in actionscript to a viewstack layer not currently showing. Are those objects not created until that layer is visible for the first time? I remember something about a creation policy, if this is the case, can I force it to create those children before that layer is viewed?
Yes, that's right -- ViewStack children are created only when needed by default ("deferred instantiation" is a phrase you'll hear thrown around in this context). If instead you want to instruct Flex to create all of the ViewStack container's children up front, consider using the creationPolicy property common to all mx.core.Containers:
A creationPolicy of
ContainerCreationPolicy.ALL means that
the navigator containers immediately
create deeper descendants for each
child, rather than waiting until that
child is selected.
<mx:ViewStack id="myStack" creationPolicy="all" />
It's a bit slower on startup, because you're creating a bunch of child components you might not need yet, but as long as you keep that tradeoff in mind, it may come in handy sometime.
Yeah, I had this same problem myself while working on an application with a PureMVC structure. I was unable to create mediators for the subcomponents of a ViewStack because they were constructed lazily by the Flex framework.
Here's where I eventually found my solution:
http://forums.puremvc.org/index.php?topic=280.0
Found the relevant documentation here. Seems like that'd be something you'd make a note of on the container docs.