views:

95

answers:

3

I'm having difficulty with a Flex app I'm creating. I believe the problem is with my poor understanding of the component lifecycle and I would greatly appreciate some pointers!

My app runs in Air. The application creates an array of DashItems. A DashItem is an ActionScript class that extends Canvas. Based on data passed on the creation of the DashItem, different components are added to this canvas. For example, if dashtype is "grid", a EvGrid is created. EvGrid is a mxml component based on DataGrid. The DashItem sets the url and calls a public function in EvGrid that initiates the HTTPService send(). Data is retrieved and and displayed in the grid. This is working as expected.

Here's the tricky part. I wish to do a scrolling display of these DashItems (think Snackr). So I set up an eventlistener for Event.ENTER_FRAME with in the main application. The function that is called scrolls the items up the screen and recycles them when they scroll off the top. When I create this eventListener immediately after creating my array of DashItems, nothing is displayed. Debugging I see the components in the DashItems receiving their data from the HTTPService, and I see my scrolling code adjusting the y settings, but nothing is seen in the application window.

When I delay the addition of the eventListener for ENTER_FRAME by setting another timer that upon completion sets the ENTER_FRAME event handler, the items appear. Sometimes, if the dataService is slow returning, however, I get an empty grid. The grid dataprovider is Bindable.

This leads me to believe that I'm trampling on some part of the component lifecycle. I'll place some code snippets below. Thanks for any help or advice to this novice.

Scroller.mxml in mx:Script section

public function handleApplicationComplete(event:Event):void {
       dataService.send();
      }
      public function faultHandler(event:FaultEvent): void {
       trace(event.toString());
      }

      public function resultHandler(event:ResultEvent): void {
       trace("returned XML: " + event.result.toString());
       for each (var i:XML in event.result.item) {
        var dx:DashItem = new DashItem({
             type: i.type,
             url: i.url.toString(),
             index: i.index,
             title: i.title,
             description: i.description,
             height: this.height/(DISPLAY_LIST_SIZE -1),
             width:  this.width * 0.9
            });

        trace("created " + dx.toString());
        DashList.unshift(dx);
       }
       buildDisplayList();
       var timer:Timer = new Timer(1000, 1);
       timer.addEventListener(TimerEvent.TIMER_COMPLETE, startAnimation);
       timer.start();
      }

      private function startAnimation(event:TimerEvent):void {
       trace("starting animation");
       addEventListener(Event.ENTER_FRAME, animate); 
      }

      private function buildDisplayList():void {
       var starty:Number = this.height;
       var listSize:Number = DISPLAY_LIST_SIZE;
       if ( DashList.length < DISPLAY_LIST_SIZE) {
        listSize = DashList.length;
       }
       for (var i:Number = 0; i < listSize; i++) {
        var di:DashItem = DashList.pop();
        displayList.unshift(di);
        di.y = starty;
        scroller.addChild(di);
        starty += di.height + PADDING;
       }
       trace("DisplayList is: ");
       traceList(displayList);
      }

Scroller's HTTPService:

<mx:HTTPService
     id="dataService"
     url="{DS_URL}"
     resultFormat="e4x"
     fault="faultHandler(event);"
     result="resultHandler(event);" />

DashItem.as snippet

public function build():void {
      if (type == "grid") {
       trace("Building EventList...");
       var ev:EvGrid = new EvGrid();
       ev.evtitle = this.title;
       this.addChild(ev);
       ev.fetchData();
      } else if (type == "StatChart") {

EvGrid snippets:

<mx:HTTPService 
        id="dataService"
        url="{ws}"
        resultFormat="e4x"
        result="resultsHandler(event);"
        fault="faultHandler(event);"
    />  

    <mx:XMLListCollection id="eventListXml" source="{xmlData.events.event}"/>
    <mx:Panel id="evwrapper" title="{evtitle}" width="100%" height="100%">

    <components:RowColorDataGrid id="EventListGrid"
      dataProvider="{eventListXml}"
      width="100%"
      height="100%"
      rowCount="{eventListXml.length+1}"
      rowColorFunction="calcRowColor">
      <components:columns>
       <mx:DataGridColumn 
        id="Serial"
        dataField="serial"
        headerText="Serial"
        width="70"

       />
       <mx:DataGridColumn 
        id="Severity"
        dataField="severity"
        headerText="Severity"
        width="60"
       />
       <mx:DataGridColumn
        id="snlStatus"
        dataField="snlstatus"
        headerText="snlStatus"
        width="100"
       />
       <mx:DataGridColumn
        id="Owneruid"
        dataField="owneruid"
        headerText="Owner"
        width="70"
       />
       <mx:DataGridColumn
        id="Node"
        dataField="node"
        headerText="Node"
        width="120"
       />
       <mx:DataGridColumn
        id="Summary"
        dataField="summary"
        headerText="Summary"
        labelFunction="getCdata"
       />
      </components:columns>
     </components:RowColorDataGrid>

    </mx:Panel

>

A: 
  1. Call setTimeout(startAnimation, 1000). Probably easier than creating a timer. Or just use the "callLater" function on UIComponents.

  2. On the same note...you can use setInterval(func, 33) instead of ENTER_FRAME (assuming aprox 30 frames/sec).

  3. For finding when an item is ready, listen for the FlexEvent.CREATION_COMPLETE event.

Glenn
Thanks for the tips. I will give them a try.
Todd
+1  A: 

I believe the problem is with my poor understanding of the component lifecycle and I would greatly appreciate some pointers

Excellent white paper on the Flex Component Lifecycle. While not specifically addressing your issue, if you feel like you want some lifecycle knowledge this will have you covered.

Joel Hooks
Thank for the Link, I will check it out.
Todd
A: 

Deepa's presentation at MAX a year or two ago is a great way to better understand the Flex component lifecycle:

http://tv.adobe.com/MAX-2008-Develop/Creating-New-Components-in-Flex-3-by-Deepa-Subramaniam.html#vi+f15384v1002

Once you grasp the invalidation schemes for properties, size and display list there is a tremendous amount you can do.

cliff.meyers
Thanks for the link!
Todd