ГИБКИЙ:диалоговое окно отображается не сразу

StackOverflow https://stackoverflow.com/questions/1410398

  •  05-07-2019
  •  | 
  •  

Вопрос

В приложении AIR у меня есть следующий код:

theDialog = PopUpManager.createPopup( this, TheDialogClass, true ) как TheDialogClass;theDialog.addEventListener(гибкий список.CREATION_COMPLETE, cpuIntensiveCalc);

В конце cpuIntensiveCalc диалоговое окно удаляется.Диалоговое окно информирует пользователя о том, что "что-то происходит, пожалуйста, будьте наготове".

Проблема в том, что cpuIntensiveCalc запускается до того, как откроется диалоговое окно.Таким образом, пользовательский опыт заключается в том, что приложение зависает на 10 секунд без индикатора, затем модальное диалоговое окно быстро (менее секунды) появляется на экране.

В документах Adobe об этом говорится о creation_complete

Отправляется, когда компонент завершит свою сборку, обработка свойств, измерение, компоновка и рисование.

Так что это похоже на правильное событие.
Во имя полноты картины я также попытался

theDialog = PopUpManager.createPopup( this, TheDialogClass, true ) как TheDialogClass;cpuIntensiveCalc();

Но имел те же результаты.

ТИА

Нет правильного решения

Другие советы

Причина этого в том, что Flash Player является однопоточным, и поэтому вы блокируете пользовательский интерфейс от реагирования на всплывающее диалоговое окно до тех пор, пока не будет завершен математический фрагмент.

Халтурное время исправления...

У вас есть два варианта.

(Это должно сработать, но не протестировано) Оберните вызов cpuIntensiveCalc() в callLater, чтобы пользовательский интерфейс мог завершить рендеринг до того, как вы заблокируете рендеринг.

Или

Используйте "Зеленые потоки", чтобы разбить вашу обработку, чтобы вы не полностью блокировали обработку пользовательского интерфейса. Взгляните.

(У меня только что была такая же проблема => даже если этот поток старый, я просто хотел внести свой вклад в решение)

(отказ от ответственности:это немного некрасиво, но они говорят, что на уровне пользовательского интерфейса это нормально...;-) )

Flex является однопоточным (по крайней мере, с точки зрения нашего разработчика, я думаю, что потоки за сценой используются виртуальной машиной).

=> обычно вы выполняете свой код в потоке пользовательского интерфейса после того, как пользователь выполнил какое-либо действие с виджетом.Любой вызов для обновления компонента пользовательского интерфейса (например, setProgress или setLabel) будет отображаться на экране только в конце цикла рендеринга (см. еще раз Жизненный цикл UIComponent).

=> В случае вызова "cpuIntensiveCalc" в callLater фреймворк отобразит ваше всплывающее окно перед выполнением метода.

Однако на практике я заметил, что обычно перед отображением всплывающего окна вам требуется выполнить пару циклов пользовательского интерфейса, например:

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 на небольшие вызываемые методы, которые могут запускаться в каждом цикле пользовательского интерфейса, иначе progressbar не будет, error, выполняться.

Используйте событие enterFrame во всплывающем окне.Не забудьте удалить прослушиватель в обработчике событий enterFrame - в противном случае в каждом кадре будет вызываться ресурсоемкий метод, приводящий к сбою вашего приложения.Если сначала это не сработает, используйте частное число в качестве счетчика и продолжайте увеличивать его в обработчике ввода кадра - вызывайте метод 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();
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top