Question

Dans une application AIR, j'ai le code suivant:

  

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

À la fin de cpuIntensiveCalc, la boîte de dialogue est supprimée. La boîte de dialogue informe l'utilisateur que "quelque chose se passe, restez en veille".

Le problème est que cpuIntensiveCalc démarre avant le dessin de la boîte de dialogue. Ainsi, l'expérience de l'utilisateur est que l'application se fige pendant 10 secondes sans indicateur, puis la boîte de dialogue modale clignote rapidement (moins d'une seconde) à l'écran.

La documentation Adobe le dit à propos de creation_complete

  

Distribué lorsque le composant a terminé sa construction,   traitement, mesure, mise en page et dessin de propriétés.

Cela ressemble donc au bon événement.
Au nom de l’exhaustivité, j’ai aussi essayé

  

theDialog = PopUpManager.createPopUp (this, TheDialogClass, true) en tant que TheDialogClass;   cpuIntensiveCalc ();

Mais a eu les mêmes résultats.

TIA

Pas de solution correcte

Autres conseils

La raison en est que Flash Player est à thread unique et vous empêchez donc l'interface utilisateur de réagir à la fenêtre contextuelle de la boîte de dialogue jusqu'à la fin du morceau de calcul.

Temps correctif ...

Vous avez deux options.

(Celui-ci devrait fonctionner, mais n'a pas encore été testé) Emballez l'appel cpuIntensiveCalc () dans un callLater, de sorte que l'interface utilisateur puisse terminer le rendu avant de bloquer le rendu.

Ou

Utilisez "Fils verts". pour casser votre traitement afin de ne pas bloquer complètement le traitement de l'interface utilisateur. Jetez un coup d'oeil .

(Je viens d'avoir le même problème = > même si ce fil est ancien, je voulais simplement apporter ma solution.)

(disclaimer: c'est un peu moche, mais ils disent que ça va dans la couche d'interface utilisateur ... ;-))

Flex est à thread unique (du moins du point de vue de notre développeur, je pense que derrière la scène, les threads sont utilisés par la VM)

= > vous exécutez généralement votre code dans le thread d'interface utilisateur après que l'utilisateur a effectué une action sur un widget. Tout appel à la mise à jour d'un composant de l'interface utilisateur (comme setProgress ou setLabel) ne sera restitué à l'écran qu'à la fin du cycle de rendu (voir à nouveau le cycle de vie UiComponent).

= > Dans l’appel "& c"; cpuIntensiveCalc " dans un callLater laissera le framework afficher votre popup avant d’exécuter la méthode.

En pratique, j’ai remarqué que vous devez généralement disposer de plusieurs cycles d’interface utilisateur avant que la fenêtre contextuelle ne soit affichée, comme ceci:

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

MuchLaterRunner étant défini comme suit:

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

    }

Le problème est le même lorsque vous appelez ensuite setProgress: nous devons diviser cpuIntensiveCalc en petites méthodes appelables qui peuvent être exécutées à chaque cycle de l'interface utilisateur, sinon la barre de progression ne sera pas erronée, elle continuera.

Utilisez l'événement enterFrame dans une fenêtre contextuelle. N'oubliez pas de supprimer le programme d'écoute dans le gestionnaire d'événements enterFrame. Dans le cas contraire, la méthode intensive du processeur sera appelée dans chaque cadre, provoquant le blocage de votre application. Si cela ne fonctionne pas dans un premier temps, utilisez un numéro privé comme compteur et continuez à l'incrémenter dans la méthode de traitement du frame enter - appelez la méthode cpu heavy uniquement lorsque le compteur atteint la valeur appropriée. Trouvez la valeur "appropriée" par trace et erreur.

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();
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top