FLEX: dialog is not displayed immediately

In an AIR application, I have the following code:

theDialog = PopUpManager.createPopUp (this, TheDialogClass, true) as TheDialogClass; theDialog.addEventListener (FlexEvent.CREATION_COMPLETE, cpuIntensiveCalc);

At the end of cpuIntensiveCalc, the dialog is deleted. The dialog informs the user that "something is happening, please wait."

The problem is that cpuIntensiveCalc is started before the dialogue starts. Thus, the user interface is that the application freezes for 10 seconds without an indicator, then the modal dialog blinks quickly (less than a second) on the screen.

Adobe docs talk about this create_complete

Dispatched when a component has completed its design, processing, measurement, layout, and drawing.

So this seems like the right event.
In the name of completeness, I also tried

theDialog = PopUpManager.createPopUp (this, TheDialogClass, true) as TheDialogClass; cpuIntensiveCalc ();

But they had the same results.

TIA

+4
source share
3 answers

The reason for this is that Flash Player is single-threaded, and therefore you block the Dialog pop-up response user interface until part of the math is completed.

Hacky Hacking Time ...

You have two options.

(This one should work, but not verified). Wrap the cpuIntensiveCalc () call in callLater so that the user interface can complete the rendering before blocking the rendering.

or

Use Green Streams to break your processing so that you don't completely block the processing of the user interface. Take a look .

+1
source

(I had the same problem =>, even if this thread is old, I just wanted to make my decision)

(disclaimer: this is a little ugly, but they say what's normal in the user interface layer ... ;-))

Flex is single-threaded (at least from the point of view of our developer, I think that VMs are used behind scene streams)

=> you usually execute your code in the user interface thread after the user has taken some action on the widgets. Any UI component update invocation (for example, setProgress or setLabel) will only be displayed on the screen at the end of the rendering cycle (see Again the UiComponent Life Cycle).

=> In the expression calling "cpuIntensiveCalc" in callLater, let the environment show your popup before executing the method.

In practice, however, I noticed that you usually should have a couple of UI dials before the popup appears, for example:

new MuchLaterRunner(popup, 7, cpuIntensiveCalc).runLater(); 

MuchLaterRunner is defined as follows:

 public class MuchLaterRunner { var uiComp:UIComponent; var currentCounter = 0; var cyclesToWaitBeforeExecution=0; var command:Function; public function MuchLaterRunner(uiComp:UIComponent, cyclesToWaitBeforeExecution:uint, command:Function) { this.uiComp = uiComp; this.command = command; this.cyclesToWaitBeforeExecution =cyclesToWaitBeforeExecution; } public function runLater() { currentCounter ++; if (currentCounter >= cyclesToWaitBeforeExecution) { uiComp.callLater(command); } else { // wait one more cycle... uiComp.callLater(runLater); } } } 

The problem arises when setProgress is called after this: we have to divide cpuIntensiveCalc into small invoked methods that can be run in each cycle of the user interface, otherwise the progress panel will not, error, progress.

+1
source

Use the enterFrame event in the popup. Remember to remove the listener in the enterFrame event handler - otherwise the intensive cpu method will be called in every frame, your application will crash. If this does not work at first, use the private number as the counter and continue to increase it in the input frame handler - call the heavy cpu method only when the counter reaches the corresponding value. Find the β€œsuitable” value by path and error.

 theDialog = PopUpManager.createPopUp(this, TheDialogClass, true) as TheDialogClass; theDialog.addEventListener(Event.ENTER_FRAME, onEnterFrame); private function onEnterFrame(e:Event):void { //can use theDialog instead of e.currentTarget here. (e.currentTarget).removeEventListener(Event.ENTER_FRAME, onEnterFrame); cpuIntensiveCalc(); } //in case the above method doesn't work, do it the following way: theDialog.addEventListener(Event.ENTER_FRAME, onEnterFrame); private var _frameCounter:Number = 0; private function onEnterFrame(e:Event):void { _frameCounter++; var desiredCount:Number = 1;//start with one - increment until it works. if(_frameCounter < desiredCount) return; //can use theDialog instead of e.currentTarget here. (e.currentTarget).removeEventListener(Event.ENTER_FRAME, onEnterFrame); cpuIntensiveCalc(); } 
0
source

All Articles