문제

AIR 애플리케이션에는 다음 코드가 있습니다.

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

cpuIntensiveCalc가 끝나면 대화 상자가 제거됩니다.대화 상자는 사용자에게 "무슨 일이 일어나고 있습니다. 잠시 기다려 주십시오."라고 알려줍니다.

문제는 대화 상자가 그려지기 전에 cpuIntensiveCalc가 시작된다는 것입니다.따라서 사용자 경험은 표시기 없이 애플리케이션이 10초 동안 정지한 다음 모달 대화 상자가 화면에서 빠르게(1초 미만) 깜박이는 것입니다.

Adobe 문서에서는 Creation_complete에 대해 이렇게 말합니다.

구성 요소가 구성, 재산 처리, 측정, 레이아웃 및 드로잉을 완료했을 때 발송되었습니다.

그래서 이것은 올바른 사건처럼 느껴집니다.
완전함의 이름으로 나도 노력해봤어

theDialog = PopUpManager.createPopUp( this, TheDialogClass, true ) as TheDialogClass;CPUIntensiveCalc();

그러나 같은 결과가 나왔습니다.

티아

올바른 솔루션이 없습니다

다른 팁

그 이유는 플래시 플레이어가 싱글 스레드로 만들기 때문에 수학 청크가 완료 될 때까지 UI가 대화 상자 팝업에 반응하는 것을 차단하고 있기 때문입니다.

해킹 수정 시간 ...

두 가지 옵션이 있습니다.

(이것은 작동하지만 테스트되지 않았습니다) CPUINTENSIVECALC () 캘리포트에서 CHPIT를 감싸서 UI가 렌더링을 차단하기 전에 렌더링을 완료 할 수 있도록합니다.

또는

"녹색 스레드"를 사용하여 처리를 분해하여 UI 처리를 완전히 차단하지 않도록하십시오. 구경하다.

(방금 동일한 문제가 발생했습니다 => 이 스레드가 오래되었더라도 내 솔루션을 제공하고 싶었습니다.)

(부인 성명:좀 보기 흉하지만 UI 레이어에서는 괜찮다고 합니다...;-) )

Flex는 단일 스레드입니다(적어도 개발자의 관점에서 볼 때 장면 뒤에서 VM이 스레드를 사용한다고 생각합니다).

=> 일반적으로 사용자가 위젯에서 일부 작업을 수행한 후 UI 스레드에서 코드를 실행합니다.UI 구성 요소(예: setProgress 또는 setLabel)를 업데이트하기 위한 모든 호출은 렌더링 주기가 끝날 때만 화면에 렌더링됩니다(UiComponent 수명 주기 다시 참조).

=> callLater에서 "cpuIntensiveCalc"를 호출하면 프레임워크가 메서드를 실행하기 전에 팝업을 표시하게 됩니다.

하지만 실제로는 팝업이 표시되기 전에 일반적으로 다음과 같이 몇 번의 UI 사이클이 필요하다는 것을 알았습니다.

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를 호출할 때 문제는 동일합니다.우리는 각 UI 주기에서 실행될 수 있는 작은 호출 가능 메서드로 cpuIntensiveCalc를 나누어야 합니다. 그렇지 않으면 진행률 표시줄이 진행되지 않습니다. 오류가 발생합니다.

팝업에서 Enterframe 이벤트를 사용하십시오. Enterframe 이벤트 핸들러에서 리스너를 제거하는 것을 잊지 마십시오. 그렇지 않으면 각 프레임에서 CPU 집약적 방법이 호출되어 앱이 충돌합니다. 처음에 작동하지 않으면 개인 번호를 카운터로 사용하고 Enter 프레임 핸들러에서 계속 증가하십시오. 카운터가 적절한 값에 도달 할 때만 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();
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top