Domanda

In un'applicazione AIR ho il seguente codice:

  

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

Alla fine di cpuIntensiveCalc la finestra di dialogo viene rimossa. La finestra di dialogo informa l'utente che "sta succedendo qualcosa, ti preghiamo di attendere."

Il problema è che cpuIntensiveCalc inizia prima che la finestra di dialogo venga disegnata. Quindi l'esperienza dell'utente è che l'applicazione si blocca per 10 secondi senza indicatore, quindi la finestra di dialogo modale lampeggia rapidamente (meno di un secondo) sullo schermo.

I documenti di Adobe dicono questo su creation_complete

  

Inviato quando il componente ha terminato la sua costruzione,   elaborazione, misurazione, layout e disegno della proprietà.

Quindi questo sembra l'evento giusto.
In nome della completezza, ho anche provato

  

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

Ma ha avuto gli stessi risultati.

TIA

Nessuna soluzione corretta

Altri suggerimenti

La ragione di ciò è che Flash Player è a thread singolo, quindi stai bloccando l'interfaccia utente dalla reazione al popup di dialogo fino al completamento del blocco matematico.

Hacky fix time ...

Hai due opzioni.

(Questo dovrebbe funzionare, ma non è stato testato) Avvolgere la chiamata cpuIntensiveCalc () in un callLater, in modo che l'interfaccia utente possa terminare il rendering prima di bloccarlo.

o

Usa " Fili verdi " per interrompere l'elaborazione in modo da non bloccare completamente l'elaborazione dell'interfaccia utente. Dai un'occhiata .

(Ho appena avuto lo stesso problema = > anche se questo thread è vecchio, volevo solo contribuire con la mia soluzione)

(dichiarazione di non responsabilità: è un po 'brutta, ma dicono che va bene nel livello dell'interfaccia utente ... ;-))

Flex è a thread singolo (almeno dal punto di vista del nostro sviluppatore, penso che i thread dietro la scena siano utilizzati dalla VM)

= > in genere esegui il tuo codice nel thread dell'interfaccia utente, dopo che l'utente ha eseguito alcune azioni su un widget. Qualsiasi chiamata per aggiornare un componente dell'interfaccia utente (come setProgress o setLabel) verrà visualizzata sullo schermo solo alla fine del ciclo di rendering (vedere di nuovo il ciclo di vita di UiComponent).

= > In therory chiamando " cpuIntensiveCalc " in un callLater consentirà al framework di visualizzare il tuo popup prima di eseguire il metodo.

In pratica, tuttavia, ho notato che in genere è necessario disporre di un paio di cicli dell'interfaccia utente prima che venga visualizzato il popup, in questo modo:

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

MuchLaterRunner viene definito in questo modo:

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

    }

Il problema è lo stesso quando si chiama setProgress in seguito: dobbiamo dividere cpuIntensiveCalc in piccoli metodi richiamabili che possono essere eseguiti in ciascun ciclo dell'interfaccia utente, altrimenti la barra di avanzamento non, errerà, avanzerà.

Usa l'evento enterFrame nel popup. Non dimenticare di rimuovere il listener nel gestore eventi enterFrame, altrimenti il ??metodo intensivo cpu verrà chiamato in ogni frame, causando l'arresto anomalo dell'app. Se all'inizio non funziona, usa un numero privato come contatore e continua ad incrementarlo nel gestore del frame di immissione - chiama il metodo pesante cpu solo quando il contatore raggiunge il valore appropriato. Trova il valore "appropriato" per traccia ed errore.

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();
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top