views:

883

answers:

4

Hi Guys, I'm having a little problem with my resize event... I created a component myself, and this component, at each resize event, runs a complex method. Here is the problem: When I maximize or restore my window, this event is called several times in a real short period of time, not letting enough time to my method to run completely before another one starts... I'd like to know if there is anyway of only run this method in the end of each resize movement. Thanks

+1  A: 

You'll want to coalesce the resize events into a single event. David Coletta talked briefly about event coalescing in this presentation, but I don't remember if he described how he did it.

You could do this in a number of ways, one of which I'll layout in pseudo code below:

resizeHandler(resizeEvent):
   if (resizeEventReceived)
       return
   resizeEventReceived = true
   Timer.startIn(30 /*ms*/).withHandler(doResize)

doResize(timerEvent):
    /* do actual resize processing */
    resizeEventReceived = false
Kaleb Pederson
+1  A: 

It sounds to me like you're doing something in your event handler that is causing a new ResizeEvent.RESIZE to be fired. Since ActionScript runs in a single thread, no independent source could possibly dispatch that event while your handler is running unless you somehow trigger it.

joshtynjala
+4  A: 

Instead of reacting to a ResizeEvent, which will fire every frame during a resize (i.e. if you hit maximize and it takes 3 frames for the component to redraw from widh/ehight = 0 to width/height = MaxValue) then the resize event will fire three times, you could 'watch' the properties of width and height.

var widthWatch:ChangeWatcher = ChangeWatcher.watch(this, 'widht', resizeHandler) var heightWatch:ChangeWatcher = ChangeWatcher.watch(this, 'height' resizeHandler)

this will, in effect, watch the properties, similar to data binding, and execute your resizeHandler whenever the width or height change. This has a slight drawback as to firing your handler twice if width and height change at the same time, but that can be solved with a third function that does the work, which gets invoked by your handlers if it isn't schedule to be invoked. The code:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="onCreationComplete(event)">
<mx:Script>
 <![CDATA[
  import mx.binding.utils.ChangeWatcher;

  private var widthWatch:ChangeWatcher;
  private var heightWatch:ChangeWatcher;
  private var resizeExecuting:Boolean = false;

  private function onCreationComplete(event:Event):void
  {
   widthWatch = ChangeWatcher.watch(this,'width',onSizeChange);
   heightWatch = ChangeWatcher.watch(this,'height',onSizeChange);
  }

  private function onSizeChange(event:Event):void
  {
   if(!resizeExecuting)
    callLater(handleResize);
   resizeExecuting = true;
  }

  private function handleResize():void
  {
   //do expensive work here
   resizeExecuting = false;
  }

  private function stopWatching()
  {
   //invoke this to stop watching the properties and prevent the handleResize method from executing
   widthWatch.unwatch();
   heightWatch.unwatch();
  }

 ]]>
</mx:Script>
</mx:Application>

I prefer the change watcher method because it fires after the width and height properties have changed, unlike a resize event wich fires before the width and height properties are correclty updated.

David
this is really cool stuff, thanks for sharing this!
Devtron
A: 

Hola,

No modifiques tu código, solo aplica el callLater. Mira este ejemplo

< mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:views="com.mmm.views.*" initialize="init()">

<![CDATA[
    import mx.events.ResizeEvent;

    private function init():void{
        addEventListener(ResizeEvent.RESIZE,positionViewStackElements)
    }
    private function positionViewStackElements(event:ResizeEvent=null):void {
        callLater(function():void{
        if(loginView!=null){
            loginView.x = getXPos(loginView);
            loginView.y = getYPos(loginView);
        }
        });
    }

    private function getXPos(obj:DisplayObject):Number {
    return (mainContent.width - obj.width) / 2;
    }

    private function getYPos(obj:DisplayObject):Number {
    return (mainContent.height - obj.height) / 2;
    }


]] > 

< /mx:Script>

< mx:Style source="/assets/styles/Aqua.css" /> 

< mx:ViewStack id="mainContent" width="100%" height="100%" creationComplete="positionViewStackElements()"> 

    < views:Login id="loginView"/> 

    < views:MainComponent id="mainComponent"/> 

< /mx:ViewStack> 

< /mx:Application>

Carlos