Apache flex FLEX:对话框不会立即显示
在AIR应用程序中,我有以下代码: Dialog=PopUpManager.createPopUp(这是DialogClass,true)作为DialogClass; Dialog.addEventListener(FlexEvent.CREATION\u COMPLETE,cpuIntensiveCalc) 在cpuIntensiveCalc结束时,将删除该对话框。该对话框通知用户“发生了一些事情,请待命。” 问题是cpuIntensiveCalc在对话框绘制之前启动。因此,用户体验是,应用程序在没有指示器的情况下冻结10秒,然后模式对话框在屏幕上快速闪烁(不到一秒) Adobe文档这样说是关于创建的 当组件完成其构造时发送, 特性处理、测量、布局和绘图 因此,这似乎是正确的事件。Apache flex FLEX:对话框不会立即显示,apache-flex,air,Apache Flex,Air,在AIR应用程序中,我有以下代码: Dialog=PopUpManager.createPopUp(这是DialogClass,true)作为DialogClass; Dialog.addEventListener(FlexEvent.CREATION\u COMPLETE,cpuIntensiveCalc) 在cpuIntensiveCalc结束时,将删除该对话框。该对话框通知用户“发生了一些事情,请待命。” 问题是cpuIntensiveCalc在对话框绘制之前启动。因此,用户体验是,应用程
以完整性的名义,我也试过了 Dialog=PopUpManager.createPopUp(这是DialogClass,true)作为DialogClass; cpuIntensiveCalc() 但结果是一样的
TIA原因是Flash播放器是单线程的,因此在数学模块完成之前,您会阻止UI对对话框弹出做出反应 骇客固定时间 你有两个选择 (这个应该可以工作,但未经测试)稍后将cpuIntensiveCalc()调用包装在callLater中,以便UI可以在阻止渲染之前完成渲染 或
使用“绿色线程”中断处理,这样就不会完全阻止UI处理 在弹出窗口中使用enterFrame事件。不要忘记删除enterFrame事件处理程序中的侦听器,否则会在每个帧中调用cpu密集型方法,导致应用程序崩溃。如果这在一开始不起作用,请使用一个专用数字作为计数器,并仅当计数器达到适当的值时,在enterframehandler-callcpu-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();
}
theDialog=PopUpManager.createPopUp(这是DialogClass,true)作为DialogClass;
Dialog.addEventListener(Event.ENTER_FRAME,onEnterFrame);
私有函数onEnterFrame(e:事件):void
{
//可以在此处使用Dialog而不是e.currentTarget。
(e.currentTarget).removeEventListener(Event.ENTER_FRAME,onEnterFrame);
cpuIntensiveCalc();
}
//如果上述方法不起作用,请按以下方法进行:
Dialog.addEventListener(Event.ENTER_FRAME,onEnterFrame);
私有变量_frameCounter:Number=0;
私有函数onEnterFrame(e:事件):void
{
_帧计数器++;
var desiredCount:Number=1;//从一个增量开始,直到它工作为止。
if(_frameCounter
(我刚刚遇到了同样的问题=>即使这个线程很旧,我也只想贡献我的解决方案)
(免责声明:这有点难看,但他们说在UI层这没关系…;-))
Flex是单线程的(至少从开发人员的角度来看,我认为虚拟机使用幕后线程)
=>通常在用户对小部件执行某些操作后,在UI线程中执行代码。任何更新UI组件(如setProgress或setLabel)的调用将仅在渲染周期结束时在屏幕上渲染(请再次参阅UiComponent生命周期)
=>在理论中,在callLater中调用“cpuIntensiveCalc”将使框架在执行方法之前显示您的弹出窗口
但实际上,我注意到,在弹出窗口显示之前,您通常需要进行几个UI循环,如下所示:
new MuchLaterRunner(popup, 7, cpuIntensiveCalc).runLater();
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);
}
}
}
MuchLaterRunner的定义如下:
new MuchLaterRunner(popup, 7, cpuIntensiveCalc).runLater();
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周期运行的小的可调用方法,否则progressbar将不会,呃,前进 哦,而且cpuIntensiveCalc没有UI更新,全是数学。是的,我后来试过打电话,没有骰子我还尝试使用计时器引入延迟。因此,我创建了弹出窗口,然后用TimerEvent.timer侦听器启动计时器。这是超级黑客,但我只是想看到它的工作。为了让它工作,我必须有相当高的延迟,比如250ms。第二个解决方案是不太粗糙的,而且对于像AS3这样的单线程系统来说可能是最好的解决方案。您还可以尝试使用活动对象模式,并将计算分解为更小的任务。