March 9th, 2007 by Kyle
Posted in: Flex, actionscript, mxml
I recently had a customer who was trying to debug his Flex components. Under certain circumstances the updateDisplayList() method of his component was getting called and it wasn’t obvious why.
In writing and debugging Flex components sometimes it would be useful to be able to see who called what method to figure out what is going on. Profilers are good for this, but unfortunately there is no Flex 2.0 (or 2.0.1) profiler. In speaking with Flex Engineer, Alex Harui (see his blog here), he suggested the strategy below:
- Subclass the component you are interested in (or if you are writing your own components just add the following to your component).
- Override the invalidateDislayList() method (or whatever method you are interested in).
- Create a new error object.
- Dump out the error objects getStackTrace() method.
This should get you the hierarchy of calls that caused the invalidateDisplayList call.
(And it is the calling of invalidateDisplayList that will flag the updateDisplayList() to be called.)
This sounded good, so I prepared the sample below. I decided to use a sample from the Flex documentation which extends VBox to make a “BottomUpVBox” which arranges items from the bottom up, the reverse of the standard VBox flow.
BottomUpVBox.as
{
import mx.containers.VBox;
import mx.core.EdgeMetrics;
import mx.core.UIComponent;
public class BottomUpVBox extends VBox
{
[Bindable]
public var callStack:String;
public function BottomUpVBox() {
super();
}
override protected function updateDisplayList(unscaledWidth:Number,
unscaledHeight:Number):void {
super.updateDisplayList(unscaledWidth, unscaledHeight);
// Get information about the container border area.
// The usable area of the container for its children is the
// container size, minus any border areas.
var vm:EdgeMetrics = viewMetricsAndPadding;
// Get the setting for the vertical gap between children.
var gap:Number = getStyle("verticalGap");
// Determine the y coordinate of the bottom of the usable area
// of the VBox.
var yOfComp:Number = height-vm.bottom;
// Temp variable for a container child.
var obj:UIComponent;
for (var i:int = 0; i < numChildren; i++)
{
// Get the first container child.
obj = UIComponent(getChildAt(i));
// Determine the y coordinate of the child.
yOfComp = yOfComp - obj.height;
// Set the x and y coordinate of the child.
// Note that you do not change the x coordinate.
obj.move(obj.x, yOfComp);
// Save the y coordinate of the child,
// plus the vertical gap between children.
// This is used to calculate the coordinate
// of the next child.
yOfComp = yOfComp - gap;
}
}
override public function invalidateDisplayList():void{
super.invalidateDisplayList();
var e:Error = new Error
callStack += "\n\n *** Call to invalidateDisplayList() *** \n";
callStack += e.getStackTrace();
trace(e.getStackTrace());
}
}
}
The code for this BottomUpVBox component is essentially that same as the code from the docs except for 2 things:
- I expose the callStack info in public, bindable variable, callStack.
- I override the invalidateDisplayList() method and as the strategy outlines, I create a new error object and get the getStackTrace()
Here is the app in which I use this BottomUpVBox and get the callStack (again essentially right from the Flex documentation).
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:MyComp="*" >
<MyComp:BottomUpVBox id="BUVB">
<mx:Label text="Label 1"/>
<mx:Button label="Button 1"/>
<mx:Label text="Label 2"/>
<mx:Button label="Button 2"/>
<mx:Label text="Label 3"/>
<mx:Button label="Button 3"/>
<mx:Label text="Label 4"/>
<mx:Button label="Button 4"/>
</MyComp:BottomUpVBox>
<mx:TextArea width="400" height="600" text="{BUVB.callStack}"/>
<mx:Button label="click to invalidateDisplayList() of BottomUpVBox" click="BUVB.invalidateDisplayList()"/>
</mx:Application>
Just running the application produces the callStack trace below, which is very informative:
*** Call to invalidateDisplayList() ***
Error
at BottomUpVBox/invalidateDisplayList()
at mx.core::UIComponent/set enabled()
at mx.core::Container/set enabled()
at mx.core::UIComponent$iinit()
at mx.core::Container$iinit()
at mx.containers::Box$iinit()
at mx.containers::VBox$iinit()
at BottomUpVBox$iinit()
at mx.core::Container/createComponentFromDescriptor()
at mx.core::Container/createComponentsFromDescriptors()
at mx.core::Container/mx.core:Container::createChildren()
at mx.core::UIComponent/initialize()
at mx.core::Container/initialize()
at mx.core::Application/initialize()
at main/initialize()
at mx.managers::SystemManager/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.managers::SystemManager/::initializeTopLevelWindow()
at mx.managers::SystemManager/::docFrameHandler()
*** Call to invalidateDisplayList() ***
Error
at BottomUpVBox/invalidateDisplayList()
at mx.core::Container/styleChanged()
at mx.core::UIComponent/http://www.adobe.com/2006/flex/mx/internal::addingChild()
at mx.core::Container/http://www.adobe.com/2006/flex/mx/internal::addingChild()
at mx.core::Container/addChildAt()
at mx.core::Container/addChild()
at mx.core::Container/createComponentFromDescriptor()
at mx.core::Container/createComponentsFromDescriptors()
at mx.core::Container/mx.core:Container::createChildren()
at mx.core::UIComponent/initialize()
at mx.core::Container/initialize()
at mx.core::Application/initialize()
at main/initialize()
at mx.managers::SystemManager/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.managers::SystemManager/::initializeTopLevelWindow()
at mx.managers::SystemManager/::docFrameHandler()
*** Call to invalidateDisplayList() ***
Error
at BottomUpVBox/invalidateDisplayList()
at mx.core::UIComponent/styleChanged()
at mx.core::Container/styleChanged()
at mx.core::UIComponent/http://www.adobe.com/2006/flex/mx/internal::addingChild()
at mx.core::Container/http://www.adobe.com/2006/flex/mx/internal::addingChild()
at mx.core::Container/addChildAt()
at mx.core::Container/addChild()
at mx.core::Container/createComponentFromDescriptor()
at mx.core::Container/createComponentsFromDescriptors()
at mx.core::Container/mx.core:Container::createChildren()
at mx.core::UIComponent/initialize()
at mx.core::Container/initialize()
at mx.core::Application/initialize()
at main/initialize()
at mx.managers::SystemManager/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.managers::SystemManager/::initializeTopLevelWindow()
at mx.managers::SystemManager/::docFrameHandler()
*** Call to invalidateDisplayList() ***
Error
at BottomUpVBox/invalidateDisplayList()
at mx.core::Container/http://www.adobe.com/2006/flex/mx/internal::addingChild()
at mx.core::Container/addChildAt()
at mx.core::Container/addChild()
at mx.core::Container/createComponentFromDescriptor()
at mx.core::Container/createComponentsFromDescriptors()
at mx.core::Container/mx.core:Container::createChildren()
at mx.core::UIComponent/initialize()
at mx.core::Container/initialize()
at mx.core::UIComponent/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.core::Container/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.core::Container/addChildAt()
at mx.core::Container/addChild()
at mx.core::Container/createComponentFromDescriptor()
at mx.core::Container/createComponentsFromDescriptors()
at mx.core::Container/mx.core:Container::createChildren()
at mx.core::UIComponent/initialize()
at mx.core::Container/initialize()
at mx.core::Application/initialize()
at main/initialize()
at mx.managers::SystemManager/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.managers::SystemManager/::initializeTopLevelWindow()
at mx.managers::SystemManager/::docFrameHandler()
*** Call to invalidateDisplayList() ***
Error
at BottomUpVBox/invalidateDisplayList()
at mx.core::Container/http://www.adobe.com/2006/flex/mx/internal::addingChild()
at mx.core::Container/addChildAt()
at mx.core::Container/addChild()
at mx.core::Container/createComponentFromDescriptor()
at mx.core::Container/createComponentsFromDescriptors()
at mx.core::Container/mx.core:Container::createChildren()
at mx.core::UIComponent/initialize()
at mx.core::Container/initialize()
at mx.core::UIComponent/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.core::Container/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.core::Container/addChildAt()
at mx.core::Container/addChild()
at mx.core::Container/createComponentFromDescriptor()
at mx.core::Container/createComponentsFromDescriptors()
at mx.core::Container/mx.core:Container::createChildren()
at mx.core::UIComponent/initialize()
at mx.core::Container/initialize()
at mx.core::Application/initialize()
at main/initialize()
at mx.managers::SystemManager/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.managers::SystemManager/::initializeTopLevelWindow()
at mx.managers::SystemManager/::docFrameHandler()
*** Call to invalidateDisplayList() ***
Error
at BottomUpVBox/invalidateDisplayList()
at mx.core::Container/http://www.adobe.com/2006/flex/mx/internal::addingChild()
at mx.core::Container/addChildAt()
at mx.core::Container/addChild()
at mx.core::Container/createComponentFromDescriptor()
at mx.core::Container/createComponentsFromDescriptors()
at mx.core::Container/mx.core:Container::createChildren()
at mx.core::UIComponent/initialize()
at mx.core::Container/initialize()
at mx.core::UIComponent/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.core::Container/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.core::Container/addChildAt()
at mx.core::Container/addChild()
at mx.core::Container/createComponentFromDescriptor()
at mx.core::Container/createComponentsFromDescriptors()
at mx.core::Container/mx.core:Container::createChildren()
at mx.core::UIComponent/initialize()
at mx.core::Container/initialize()
at mx.core::Application/initialize()
at main/initialize()
at mx.managers::SystemManager/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.managers::SystemManager/::initializeTopLevelWindow()
at mx.managers::SystemManager/::docFrameHandler()
*** Call to invalidateDisplayList() ***
Error
at BottomUpVBox/invalidateDisplayList()
at mx.core::Container/http://www.adobe.com/2006/flex/mx/internal::addingChild()
at mx.core::Container/addChildAt()
at mx.core::Container/addChild()
at mx.core::Container/createComponentFromDescriptor()
at mx.core::Container/createComponentsFromDescriptors()
at mx.core::Container/mx.core:Container::createChildren()
at mx.core::UIComponent/initialize()
at mx.core::Container/initialize()
at mx.core::UIComponent/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.core::Container/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.core::Container/addChildAt()
at mx.core::Container/addChild()
at mx.core::Container/createComponentFromDescriptor()
at mx.core::Container/createComponentsFromDescriptors()
at mx.core::Container/mx.core:Container::createChildren()
at mx.core::UIComponent/initialize()
at mx.core::Container/initialize()
at mx.core::Application/initialize()
at main/initialize()
at mx.managers::SystemManager/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.managers::SystemManager/::initializeTopLevelWindow()
at mx.managers::SystemManager/::docFrameHandler()
*** Call to invalidateDisplayList() ***
Error
at BottomUpVBox/invalidateDisplayList()
at mx.core::Container/http://www.adobe.com/2006/flex/mx/internal::addingChild()
at mx.core::Container/addChildAt()
at mx.core::Container/addChild()
at mx.core::Container/createComponentFromDescriptor()
at mx.core::Container/createComponentsFromDescriptors()
at mx.core::Container/mx.core:Container::createChildren()
at mx.core::UIComponent/initialize()
at mx.core::Container/initialize()
at mx.core::UIComponent/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.core::Container/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.core::Container/addChildAt()
at mx.core::Container/addChild()
at mx.core::Container/createComponentFromDescriptor()
at mx.core::Container/createComponentsFromDescriptors()
at mx.core::Container/mx.core:Container::createChildren()
at mx.core::UIComponent/initialize()
at mx.core::Container/initialize()
at mx.core::Application/initialize()
at main/initialize()
at mx.managers::SystemManager/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.managers::SystemManager/::initializeTopLevelWindow()
at mx.managers::SystemManager/::docFrameHandler()
*** Call to invalidateDisplayList() ***
Error
at BottomUpVBox/invalidateDisplayList()
at mx.core::Container/http://www.adobe.com/2006/flex/mx/internal::addingChild()
at mx.core::Container/addChildAt()
at mx.core::Container/addChild()
at mx.core::Container/createComponentFromDescriptor()
at mx.core::Container/createComponentsFromDescriptors()
at mx.core::Container/mx.core:Container::createChildren()
at mx.core::UIComponent/initialize()
at mx.core::Container/initialize()
at mx.core::UIComponent/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.core::Container/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.core::Container/addChildAt()
at mx.core::Container/addChild()
at mx.core::Container/createComponentFromDescriptor()
at mx.core::Container/createComponentsFromDescriptors()
at mx.core::Container/mx.core:Container::createChildren()
at mx.core::UIComponent/initialize()
at mx.core::Container/initialize()
at mx.core::Application/initialize()
at main/initialize()
at mx.managers::SystemManager/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.managers::SystemManager/::initializeTopLevelWindow()
at mx.managers::SystemManager/::docFrameHandler()
*** Call to invalidateDisplayList() ***
Error
at BottomUpVBox/invalidateDisplayList()
at mx.core::Container/http://www.adobe.com/2006/flex/mx/internal::addingChild()
at mx.core::Container/addChildAt()
at mx.core::Container/addChild()
at mx.core::Container/createComponentFromDescriptor()
at mx.core::Container/createComponentsFromDescriptors()
at mx.core::Container/mx.core:Container::createChildren()
at mx.core::UIComponent/initialize()
at mx.core::Container/initialize()
at mx.core::UIComponent/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.core::Container/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.core::Container/addChildAt()
at mx.core::Container/addChild()
at mx.core::Container/createComponentFromDescriptor()
at mx.core::Container/createComponentsFromDescriptors()
at mx.core::Container/mx.core:Container::createChildren()
at mx.core::UIComponent/initialize()
at mx.core::Container/initialize()
at mx.core::Application/initialize()
at main/initialize()
at mx.managers::SystemManager/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.managers::SystemManager/::initializeTopLevelWindow()
at mx.managers::SystemManager/::docFrameHandler()
*** Call to invalidateDisplayList() ***
Error
at BottomUpVBox/invalidateDisplayList()
at mx.core::Container/http://www.adobe.com/2006/flex/mx/internal::addingChild()
at mx.core::Container/addChildAt()
at mx.core::Container/addChild()
at mx.core::Container/createComponentFromDescriptor()
at mx.core::Container/createComponentsFromDescriptors()
at mx.core::Container/mx.core:Container::createChildren()
at mx.core::UIComponent/initialize()
at mx.core::Container/initialize()
at mx.core::UIComponent/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.core::Container/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.core::Container/addChildAt()
at mx.core::Container/addChild()
at mx.core::Container/createComponentFromDescriptor()
at mx.core::Container/createComponentsFromDescriptors()
at mx.core::Container/mx.core:Container::createChildren()
at mx.core::UIComponent/initialize()
at mx.core::Container/initialize()
at mx.core::Application/initialize()
at main/initialize()
at mx.managers::SystemManager/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.managers::SystemManager/::initializeTopLevelWindow()
at mx.managers::SystemManager/::docFrameHandler()
*** Call to invalidateDisplayList() ***
Error
at BottomUpVBox/invalidateDisplayList()
at mx.core::UIComponent/mx.core:UIComponent::childrenCreated()
at mx.core::UIComponent/initialize()
at mx.core::Container/initialize()
at mx.core::UIComponent/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.core::Container/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.core::Container/addChildAt()
at mx.core::Container/addChild()
at mx.core::Container/createComponentFromDescriptor()
at mx.core::Container/createComponentsFromDescriptors()
at mx.core::Container/mx.core:Container::createChildren()
at mx.core::UIComponent/initialize()
at mx.core::Container/initialize()
at mx.core::Application/initialize()
at main/initialize()
at mx.managers::SystemManager/http://www.adobe.com/2006/flex/mx/internal::childAdded()
at mx.managers::SystemManager/::initializeTopLevelWindow()
at mx.managers::SystemManager/::docFrameHandler()
*** Call to invalidateDisplayList() ***
Error
at BottomUpVBox/invalidateDisplayList()
at mx.core::Container/styleChanged()
at mx.core::UIComponent/notifyStyleChangeInChildren()
at mx.core::Container/mx.core:Container::commitProperties()
at mx.core::UIComponent/validateProperties()
at mx.managers::LayoutManager/::validateProperties()
at mx.managers::LayoutManager/::doPhasedInstantiation()
at Function/http://adobe.com/AS3/2006/builtin::apply()
at mx.core::UIComponent/::callLaterDispatcher2()
at mx.core::UIComponent/::callLaterDispatcher()
*** Call to invalidateDisplayList() ***
Error
at BottomUpVBox/invalidateDisplayList()
at mx.core::UIComponent/styleChanged()
at mx.core::Container/styleChanged()
at mx.core::UIComponent/notifyStyleChangeInChildren()
at mx.core::Container/mx.core:Container::commitProperties()
at mx.core::UIComponent/validateProperties()
at mx.managers::LayoutManager/::validateProperties()
at mx.managers::LayoutManager/::doPhasedInstantiation()
at Function/http://adobe.com/AS3/2006/builtin::apply()
at mx.core::UIComponent/::callLaterDispatcher2()
at mx.core::UIComponent/::callLaterDispatcher()
*** Call to invalidateDisplayList() ***
Error
at BottomUpVBox/invalidateDisplayList()
at mx.core::UIComponent/validateSize()
at mx.managers::LayoutManager/::validateSize()
at mx.managers::LayoutManager/::doPhasedInstantiation()
at Function/http://adobe.com/AS3/2006/builtin::apply()
at mx.core::UIComponent/::callLaterDispatcher2()
at mx.core::UIComponent/::callLaterDispatcher()
*** Call to invalidateDisplayList() ***
Error
at BottomUpVBox/invalidateDisplayList()
at mx.core::UIComponent/validateSize()
at mx.managers::LayoutManager/::validateSize()
at mx.managers::LayoutManager/::doPhasedInstantiation()
at Function/http://adobe.com/AS3/2006/builtin::apply()
at mx.core::UIComponent/::callLaterDispatcher2()
at mx.core::UIComponent/::callLaterDispatcher()
*** Call to invalidateDisplayList() ***
Error
at BottomUpVBox/invalidateDisplayList()
at mx.core::UIComponent/validateSize()
at mx.managers::LayoutManager/::validateSize()
at mx.managers::LayoutManager/::doPhasedInstantiation()
at Function/http://adobe.com/AS3/2006/builtin::apply()
at mx.core::UIComponent/::callLaterDispatcher2()
at mx.core::UIComponent/::callLaterDispatcher()
*** Call to invalidateDisplayList() ***
Error
at BottomUpVBox/invalidateDisplayList()
at mx.core::UIComponent/validateSize()
at mx.managers::LayoutManager/::validateSize()
at mx.managers::LayoutManager/::doPhasedInstantiation()
at Function/http://adobe.com/AS3/2006/builtin::apply()
at mx.core::UIComponent/::callLaterDispatcher2()
at mx.core::UIComponent/::callLaterDispatcher()
*** Call to invalidateDisplayList() ***
Error
at BottomUpVBox/invalidateDisplayList()
at mx.core::UIComponent/validateSize()
at mx.managers::LayoutManager/::validateSize()
at mx.managers::LayoutManager/::doPhasedInstantiation()
at Function/http://adobe.com/AS3/2006/builtin::apply()
at mx.core::UIComponent/::callLaterDispatcher2()
at mx.core::UIComponent/::callLaterDispatcher()
*** Call to invalidateDisplayList() ***
Error
at BottomUpVBox/invalidateDisplayList()
at mx.core::UIComponent/validateSize()
at mx.managers::LayoutManager/::validateSize()
at mx.managers::LayoutManager/::doPhasedInstantiation()
at Function/http://adobe.com/AS3/2006/builtin::apply()
at mx.core::UIComponent/::callLaterDispatcher2()
at mx.core::UIComponent/::callLaterDispatcher()
*** Call to invalidateDisplayList() ***
Error
at BottomUpVBox/invalidateDisplayList()
at mx.core::UIComponent/validateSize()
at mx.managers::LayoutManager/::validateSize()
at mx.managers::LayoutManager/::doPhasedInstantiation()
at Function/http://adobe.com/AS3/2006/builtin::apply()
at mx.core::UIComponent/::callLaterDispatcher2()
at mx.core::UIComponent/::callLaterDispatcher()
*** Call to invalidateDisplayList() ***
Error
at BottomUpVBox/invalidateDisplayList()
at mx.core::UIComponent/validateSize()
at mx.managers::LayoutManager/::validateSize()
at mx.managers::LayoutManager/::doPhasedInstantiation()
at Function/http://adobe.com/AS3/2006/builtin::apply()
at mx.core::UIComponent/::callLaterDispatcher2()
at mx.core::UIComponent/::callLaterDispatcher()
*** Call to invalidateDisplayList() ***
Error
at BottomUpVBox/invalidateDisplayList()
at mx.core::UIComponent/validateSize()
at mx.core::Container/validateSize()
at mx.managers::LayoutManager/::validateSize()
at mx.managers::LayoutManager/::doPhasedInstantiation()
at Function/http://adobe.com/AS3/2006/builtin::apply()
at mx.core::UIComponent/::callLaterDispatcher2()
at mx.core::UIComponent/::callLaterDispatcher()
*** Call to invalidateDisplayList() ***
Error
at BottomUpVBox/invalidateDisplayList()
at mx.core::UIComponent/setActualSize()
at mx.containers.utilityClasses::Flex$/flexChildHeightsProportionally()
at mx.containers.utilityClasses::BoxLayout/updateDisplayList()
at mx.containers.utilityClasses::ApplicationLayout/updateDisplayList()
at mx.core::LayoutContainer/mx.core:LayoutContainer::updateDisplayList()
at mx.core::Application/mx.core:Application::updateDisplayList()
at mx.core::UIComponent/validateDisplayList()
at mx.core::Container/validateDisplayList()
at mx.managers::LayoutManager/::validateDisplayList()
at mx.managers::LayoutManager/::doPhasedInstantiation()
at Function/http://adobe.com/AS3/2006/builtin::apply()
at mx.core::UIComponent/::callLaterDispatcher2()
at mx.core::UIComponent/::callLaterDispatcher()
I hope some of you will find this useful.
A complete Flex Builder 2.0.1 Project Archive (.zip) of this sample can be found here.





March 10th, 2007 at 3:48 pm
This technique only works under the debug Flash player. In the release Flash player, stack info isn’t maintained. Of course, most of the time you need it, it’ll be in the debug player. But don’t go trying to use code like this in production to write diagnostic logs or anything.
March 10th, 2007 at 9:48 pm
Good call. You are correct. The call stack is only maintained in the debug player. Thanks.