开发者

Why am I getting this "Cannot access a property or method of a null object reference" error?

I'm new to flex and actionscript. I'm trying to create a small flex app that has multiple states, but if I have nested containers, it looks like some of the objects are not getting initialized when I expected them to be, even when I have the creationPolicy set to "all."

I've reduced the issue to a small example, with a commented block showing when it does work.

Using the existing code, I get this error: "TypeError: Error #1009: Cannot access a property or method of a null object reference at main/init()" and the event handlers are not installed.

If I instead use the commented block, which has the Panel and VBox elements removed, it does work.

I know I could add a click attribute to the mxml elements, but this is just a simplified example, and I'm more interested knowing why the objects are not initialized when the app loads.

<mx:Application 
  xmlns:mx="http://www.adobe.com/2006/mxml"
  applicationComplete="init();"
  currentState="start">

<mx:Script>
  private function mainButtonHandler(event:Event):void{
    currentState = "start"
  }

  private function startButtonHandler(event:Event):void {
    currentState = "main";
  }

  public function init():void{
    mainButton.addEventListener(MouseEvent.CLICK, mainButtonHandler);
    startButton.addEventListener(MouseEvent.CLICK, startButtonHandler);
  }
</mx:Script>

<!-- this does not work -->
<mx:states>
  <mx:State name="main"> 
    <mx:AddChild creationPolicy="all">
      <mx:Panel creationPolicy="all">
        <mx:VBox creationPolicy="all">
          <mx:Button id="mainButton" label="Change to Start State"/>
        </mx:VBox>
      </mx:Panel>
    </mx:AddChild>
  </mx:State>

  <mx:State name="start"> 
    <mx:AddChild creationPolicy="all">
      <mx:Panel creationPolicy="all">
        <mx:VBox creationPolicy="all">
          <mx:Button id="startButton" label="Change to Main state"/>
        </mx:VBox>
      </mx:Panel>
    </mx:AddChild>
  </mx:State>
</mx:states>

<!-- this works -->
<!--
<mx:states>
  <mx:State name="main"> 
    <mx:AddChild creationPolicy="all">
      <mx:Button id="mainButton" label="Change to Start State"/&g开发者_StackOverflowt;
    </mx:AddChild>
  </mx:State>

  <mx:State name="start"> 
    <mx:AddChild creationPolicy="all">
      <mx:Button id="startButton" label="Change to Main state"/>
    </mx:AddChild>
  </mx:State>
</mx:states>
-->

</mx:Application>

Thanks for any feedback.


What if you will make next thing:

 <mx:State name="main"> 
      <mx:Panel creationPolicy="all">
        <mx:VBox creationPolicy="all">
         <mx:AddChild creationPolicy="all">
          <mx:Button id="mainButton" label="Change to Start State"/>
         </mx:AddChild>
        </mx:VBox>
      </mx:Panel>    
  </mx:State>

if you dont like this, switch your Button to custom component Based on Panel with VBox and Button, so you will rewrite it to almost like commented code, but you will use a containers.

And if we will answer to question Why this weird stuff about access comes true:

because you use 3 containers: Panel VBox and Button, and events dispatching all is done to application/creation-Complete after only panel is completed, not its children.

Clear?


  1. I think that business is in applicationComplete event, use creationComplete instead.
  2. In your code you said that commented code works in addChild, because it doesn't have double containers, as in uncommented code, such as Button Inside VBox inside of Panel.
  3. And finally, my advice is: please left all old flex version, and migrate to Flex 4 Gumbo, because it have great states logic.

Best Regards
Eugene


Since the creationPolicy="all" attribute does not work the way I thought it would, then for complex state changes I set up a 'state initialization' method for each state, keyed off of the currentStateChange event. Here's an example of what I did, which also include an update to use Flex 4 states, even though I'm not using spark components in the example.

<s:Application 
  xmlns:fx="http://ns.adobe.com/mxml/2009"
  xmlns:mx="library://ns.adobe.com/flex/mx"
  xmlns:s="library://ns.adobe.com/flex/spark"
  applicationComplete="init();"
  currentStateChange="stateChange(event);"
  creationPolicy="all"
  currentState="bar"
  >

<fx:Script>
  import mx.controls.Alert;
  import mx.events.StateChangeEvent;

  private var InittedStates:Object = new Object();

  private function mainButtonHandler(event:Event):void{
    currentState = "bar"
  }

  private function startButtonHandler(event:Event):void {
    currentState = "foo";
  }

  public function stateChange(event:StateChangeEvent):void{
      if (event.newState === 'bar'){
        initBarState();
      }   
      else if(event.newState === 'foo'){
        initFooState();
      }   
  }

  public function initBarState():void {
    if (InittedStates.bar){ 
      return;
    }   
    startButton.addEventListener(MouseEvent.CLICK, startButtonHandler);
    InittedStates.bar = true;
  }

  public function initFooState():void {
    if (InittedStates.foo){ 
      return;
    }   
    mainButton.addEventListener(MouseEvent.CLICK, mainButtonHandler);
    InittedStates.foo = true;
  }

  public function init():void{
  }
</fx:Script>

<s:states>
  <s:State name="foo"/>
  <s:State name="bar"/>
</s:states>


<mx:Panel includeIn="foo" creationPolicy="all">
  <mx:VBox creationPolicy="all">
    <mx:Button id="mainButton" label="Change to Start State"/>
  </mx:VBox>
</mx:Panel>

<mx:Panel includeIn="bar" creationPolicy="all">
  <mx:VBox creationPolicy="all">
    <mx:Button id="startButton" label="Change to Main state"/>
  </mx:VBox>
</mx:Panel>

</s:Application>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜