2009-09-11 61 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週期運行的小型可調用方法,否則進度條不會錯誤地進行。