我正在开发一个具有此AdvancedDataGrid组件的应用程序。其中一列有字符串格式的日期(mm / dd / yyyy) - 所以要根据日期排序,我写了一个函数来调用该列的sortCompare属性:
private function sortDueDate(item1: Object, item2: Object): int {
this.showPleaseWaitMessage();
// collect the date values as string and convert into Date objects:
var date1: Date = new Date(Date.parse(item1.allocationDate));
var date2: Date = new Date(Date.parse(item2.allocationDate));
// compare the 2 date objects:
return ObjectUtil.dateCompare(date1, date2);
}
此功能适用于5000行数据。很明显,预计会减慢甚至冻结应用程序5-10秒。但是这种sortCompare函数需要大约40-45秒来对数据进行排序。这肯定会让最终用户感到困惑。
所以我写了另一个从上面的sortDueDate()调用的函数来显示一条消息 - “请等待数据被排序。”
private function showPleaseWaitMessage(): void {
// show message only if this is the 1st iteration:
if(sortIteration == 1) { // sortIteration is a private uint only for counting iteration and showing the message at 1st iteration
formattedAlert = Alert.show("Please wait while the data is being sorted.", "Information", Alert.OK, this, pleaseWaitMessageHandler);
formattedAlert.styleName = "Alert";
// set busy cursor:
CursorManager.setBusyCursor();
sortIteration++;
}
else {
// do nothing
}
}
private function pleaseWaitMessageHandler(eventObj: CloseEvent): void {
// stop busy cursor:
CursorManager.removeBusyCursor();
// reset the iteration no. after sorting is complete
sortIteration = 1;
}
在我尝试运行应用程序之前,所有这些都很好看。但是显示带有忙碌光标的消息的所有努力都是徒劳的,因为所有这些仅在应用程序冻结40-45秒后才会显示。并且在显示消息时,排序在后台完成。 我不能使用分页,因为我们的客户反对这一点,令人惊讶但真实:-)
任何人都可以建议解决这个问题,以便在排序开始之前向用户显示消息......处理这种情况的任何输入都将非常感激!
提前致谢!
答案 0 :(得分:2)
UI锁定的原因是Flash使用单线程事件循环。每个循环包括几个阶段,其中调度系统事件,调用事件处理程序,最后执行渲染。如果您的代码没有及时向Flash发布控制权,那么整个应用程序就会被冻结。
这是一篇很好的文章,说明了这个概念:Elastic Racetrack for Flash 9 and AVM2
有一些解决方案。最简单的方法是在显示等待消息时允许应用程序锁定(如果应用程序冻结45秒就可以了)。为此,我们需要允许Flash播放器在执行排序之前进行渲染。为此,您可以创建一个ENTER_FRAME
事件处理程序,以便在下一帧开始时调用逻辑(在代码将等待消息添加到DisplayList
之后)。例如:
stage.addEventListener(Event.ENTER_FRAME, myFunction);
function myFunction(event:Event) {
// invoke sort logic here
}
另一个解决方案(使用这个概念)是将分类分解成可以分布在几个帧上的较小块的工作,从而允许事件循环循环。
但是,理想的解决方案是利用Flash Player 12的新Worker功能。这允许您在单独的执行线程中执行处理。这可以通过从主应用程序代码调用worker(为其提供所需的数据)并添加一个事件监听器来响应一旦作业完成 - 从而永远不会锁定主事件循环。有关工人的更多信息,请阅读:Worker - AS3
答案 1 :(得分:0)
我终于能够在使用TEXT格式的Date值对列进行排序时解决应用程序冻结的问题。网格有超过5000条记录,此解决方案自动将冻结时间减少到不到5秒(应用程序冻结时间超过45秒)。这就是我的所作所为:
我为AdvancedDataGrid的HEADER_RELEASE事件注册了一个事件监听器:
dgMyGridHere.addEventListener(AdvancedDataGridEvent.HEADER_RELEASE, startSorting);
然后在侦听器方法中,我只检查了no.of记录是否超过1000(大约1000条记录的排序是在闪存中完成的,所以不需要向用户显示消息)。
/**
* FUNCTION TO HANDLE THE COLUMN-SORT EVENT.
**/
private function startSorting(event: AdvancedDataGridEvent): void {
// show message to user with busy cursor only if row-count is > 1000
if(orgData.length > 1000) {
this.showPleaseWaitMessage();
// set busy cursor:
CursorManager.setBusyCursor();
// set timer to 5 secs, so that busy cursor is removed after 5 seconds:
timer = new Timer(5000, 1);
timer.addEventListener(TimerEvent.TIMER, removeBusyCursor);
timer.start();
}
else {
// no need to show message
}
var sortEvent:AdvancedDataGridEvent = new AdvancedDataGridEvent(AdvancedDataGridEvent.SORT);
dgAnnualAdvisoryMeeting.dispatchEvent(sortEvent);
}
/**
* FUNCTION TO SHOW A "PLEASE WAIT" MESSAGE.
**/
private function showPleaseWaitMessage(): void {
formattedAlert = Alert.show("Please wait while the data is being sorted.", "Information");
formattedAlert.styleName = "Alert";
}
我还将计时器设置为5秒以移除忙碌光标(只是为了让用户知道排序已完成 - 虽然时间不到5秒),这里是计时器监听器事件处理程序:
/**
* FUNCTION TO HANDLE THE 5 SECONDS TIMER EVENT AND STOP THE BUSY CURSOR.
**/
private function removeBusyCursor(timerEvent: TimerEvent): void {
// stop busy cursor:
CursorManager.removeBusyCursor();
}
那就是它!我希望这有助于任何面临类似问题的人。 感谢Peter让我深入了解了#34; The Frame"处理,但我以另一种方式解决了问题:-) 还有来自" Christofer Dutz"在他的帖子中:
https://dev.c-ware.de/confluence/display/PUBLIC/Programatically+sort+AdvancedDataGrid+columns