FLEX:对话框不会立即显示

时间:2009-09-11 11:40:33

标签: flex air

在AIR应用程序中,我有以下代码:

  

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

在cpuIntensiveCalc结束时,将删除该对话框。该对话框通知用户“正在发生的事情,请等待。”

问题是cpuIntensiveCalc在对话框绘制之前启动。因此,用户体验是应用程序在没有指示器的情况下冻结10秒钟,然后模式对话框在屏幕上快速闪烁(不到一秒钟)。

Adob​​e文档说这是关于creation_complete

  

组件完成构建后调度,   物业处理,测量,布局和绘图。

所以这感觉就像是正确的事件 在完整性的名义,我也试过

  

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

但结果相同。

TIA

3 个答案:

答案 0 :(得分:1)

原因是Flash Player是单线程的,因此您阻止UI对Dialog Popup做出反应,直到数学块完成。

Hacky修复时间......

您有两种选择。

(这个应该可以工作,但是未经测试)在callLater中包装cpuIntensiveCalc()调用,以便在阻止渲染之前UI可以完成渲染。

或者

使用“绿色线程”来分解您的处理,这样您就不会完全阻止UI处理。 Take a look

答案 1 :(得分:1)

(我刚才有同样的问题=>即使这个帖子已经老了,我只想提供我的解决方案)

(免责声明:这有点难看,但他们说在UI层中没问题...... ;-))

Flex是单线程的(至少从我们的开发人员的角度来看,我认为VM背后的场景线程)

=>在用户对窗口小部件执行某些操作后,通常在UI线程中执行代码。任何更新UI组件的调用(如setProgress或setLabel)都只会在渲染周期结束时在屏幕上呈现(再次参见UiComponent生命周期)。

=>在callLater中调用“cpuIntensiveCalc”会让框架在执行方法之前显示弹出窗口。

在实践中,我注意到在显示弹出窗口之前,您通常必须拥有几个UI循环,如下所示:

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

MuchLaterRunner的定义如下:

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);
            }
        }

    }

之后调用setProgress时的问题是相同的:我们必须将cpuIntensiveCalc分成可在每个UI周期运行的小型可调用方法,否则进度条不会,错误,进展。

答案 2 :(得分:0)

在弹出窗口中使用enterFrame事件。不要忘记在enterFrame事件处理程序中删除侦听器 - 否则将在每个帧中调用cpu密集型方法,从而导致应用程序崩溃。如果这首先不起作用,请使用专用号码作为计数器,并在输入帧处理程序中继续增加它 - 仅当计数器达到适当的值时才调用cpu heavy方法。通过跟踪和错误找到“适当的”值。

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();
}
相关问题