2009-09-11 92 views
4

显示在AIR应用程序我有以下代码:FLEX:对话框不立即

theDialog = PopUpManager.createPopUp(此,TheDialogClass,真)作为TheDialogClass; theDialog.addEventListener(FlexEvent.CREATION_COMPLETE,cpuIntensiveCalc);

在cpuIntensiveCalc的末尾,对话框被删除。该对话框通知用户“发生了什么事,请等待。”

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

Adob​​e的文档说这有关CREATION_COMPLETE

当组件完成其构建, 属性处理,测量,布置和绘制时调度。

所以这感觉就像是正确的事件。
在完整性的名称,我还试图

theDialog = PopUpManager.createPopUp(此,TheDialogClass,真)作为TheDialogClass; cpuIntensiveCalc();

但是得到了同样的结果。

TIA

+0

哦,和cpuIntensiveCalc没有UI更新,它的所有数学。 – PaulC 2009-09-11 13:54:06

回答

1

这样做的原因是,Flash播放器是单线程的,所以你是从,直到数学块完成反应,对话框弹出阻塞UI。

哈克修复时间...

您有两种选择。

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

或者

使用“绿色线程”分手的处理,这样你就不能完全阻断UI处理。 Take a look

+0

是的,我试过callLater,没有骰子。 :| 我也尝试过使用定时器来引入延迟。所以我创建弹出窗口,然后用TimerEvent.TIMER侦听器启动计时器。这是超级哈克,但我只是想看看它的工作。为了使它工作,我不得不有很长的延迟,如250毫秒。 – PaulC 2009-09-11 14:56:46

+0

第二种解决方案对于像AS3这样的单线程系统来说可能更简单,也许是最好的解决方案。您也可以尝试活动对象模式,并将您的计算分解为更小的任务。 http://en.wikipedia.org/wiki/Active_object – Glenn 2009-09-11 22:33:21

0

在弹出窗口上使用enterFrame事件。不要忘记在enterFrame事件处理程序中删除监听器 - 否则将在每个帧中调用cpu密集型方法,导致应用程序崩溃。如果这不起作用,请使用专用号码作为计数器并将其递增到输入帧处理程序中 - 只有当计数器达到适当的值时才调用CPU繁重方法。通过跟踪和错误找到“适当”的值。

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

(我有同样的问题=>即使这个线程是旧的,我只是想贡献自己的解决方案)

(免责声明:这是一个有点难看,但他们说这是在确定UI层...;-))

Flex是单线程(从我们的开发人员的角度至少,我觉得现场线程由VM使用)

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

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

但在实践中,我注意到你通常必须有一对夫妇UI cylces的显示弹出之前,像这样:

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周期运行的小型可调用方法,否则进度条不会错误地进行。