Flex TabNavigator null object issue

727 views Asked by At

I am having trouble with TabNavigator that it always dispatch error:

TypeError: Error #1009: Cannot access a property or method of a null object reference.
at mx.containers::TabNavigator/keyDownHandler()[/Users/justinmclean/Documents/ApacheFlex4.11.0/frameworks/projects/mx/src/mx/containers/TabNavigator.as:903]

Example code:

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
                   xmlns:s="library://ns.adobe.com/flex/spark" 
                   xmlns:mx="library://ns.adobe.com/flex/mx" applicationComplete="init(event)">
<fx:Script>
    <![CDATA[
        import mx.events.FlexEvent;

        protected function init(event:FlexEvent):void
        {
            stage.addEventListener(KeyboardEvent.KEY_DOWN, handleKeyDown);
        }

        public function handleKeyDown(event:KeyboardEvent):void
        {
            if(event.keyCode == Keyboard.F1){
                if(currentState=="State1"){
                    currentState = "setting";
                }else{
                    currentState = "State1";
                }
            }
        }
    ]]>
</fx:Script>
<fx:Declarations>
    <!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:states>
    <s:State name="State1"/>
    <s:State name="setting"/>
</s:states>

<s:BorderContainer left="0" right="0" top="0" bottom="0" includeIn="setting">
<mx:TabNavigator id="TabNavigator" left="10" right="10" top="110" bottom="10" creationPolicy="all">
    <!-- General Tab -->
    <s:NavigatorContent id="generaltab" width="100%" height="100%" label="General">
        <s:Group id="generalcontainer">
        </s:Group>
    </s:NavigatorContent>
    <!-- Screen Tab -->
    <s:NavigatorContent id="screentab" width="100%" height="100%" label="Screen">
        <s:Group id="screencontainer" width="100%" height="100%">
        </s:Group>
    </s:NavigatorContent>
    <!-- Playlist Tab -->
    <s:NavigatorContent id="playlisttab" width="100%" height="100%" label="Playlist">
        <s:Group id="playlistcontainer">    
        </s:Group>
    </s:NavigatorContent>
</mx:TabNavigator>
    </s:BorderContainer>
</s:WindowedApplication>

When I press on F1, it will jump to setting page. Which will show the tabnavigator. Press F1 again to hide it.

Basically, there is no problem to show and hide the tab navigator repeatedly. But if I clicked any tab before hide the tab navigator, when I try to show the tab navigator again by pressing F1 on keyboard, it dispatch error as I showed above.

How can I solve / prevent the error from occurring?

Thank you.

2

There are 2 answers

0
user1995781 On BEST ANSWER

I just found a way to prevent the bug from occurring. That is by adding TabNavigator.stage.focus=null; before changing the state back to State1

3
RIAstar On

Looks like you've stumbled on a bug in the SDK (which frankly worries me a bit, because it means some event listeners are not being disposed of properly).

Look at the source where the error occurs:

override protected function keyDownHandler(event:KeyboardEvent):void
{
    if (focusManager.getFocus() == this)
    {
        // Redispatch the event from the TabBar so that it can handle it.
        tabBar.dispatchEvent(event);
    }
}

What happens is that when you go from State1 to setting, the TabNavigator is initially not on the displayList (you're in the process of adding it through includeIn), hence it has no focusManager. That's perfectly normal; what is not normal is that the keyDownHandler method is executed for a component that is not currently on the displayList. This eventually results in that nullpointer exception because there is no focusManager when the method is executed.
It looks like the framework doesn't clean up the event listener when the parent of the TabNavigator is removed. It does work correctly when TabNavigator itself is being added/removed with includeIn itself, so luckily for you the workaround is quite simple:

<s:BorderContainer includeIn="setting">
    <mx:TabNavigator id="TabNavigator" includeIn="setting" creationPolicy="all">

You might want to register this bug in the Apache Flex JIRA