Flex组件未显示(有时) - 奇怪的行为 - flex 3 updateCompletePendingFlag

时间:2012-08-23 20:48:40

标签: flex custom-component flex-mx

我有点问题。

环境

环境:Flex 3(实际更新为Flex 4 SDK,但仍使用 mx 而不是 spark

IDE:Flash Builder 4.6。

浏览器:Firefox 14.0.1

Flash播放器版本:FP 11调试器 - 11.2.202.235

状态语法:Flex 3样式语法。

申请

我有一个申请。

此应用程序有几种状态。

其中一个州又有一个“wrapperComponent”,它有三种不同的状态:基本状态(即“”),“firstState”和“secondState”。

稍微简化一下,几乎每个状态包含的是一个不同的自定义组件,如下所示:

  • wrapperComponent” - > “base comp.
  • firstState” - > “first comp.
  • secondState”和“second comp.

下图更清楚地显示了情况:

Hierarchy of the application components and states

然后,当用户使用“wrapperComponent”时,它首先到达“firstState”,然后他使用“base state”,之后,他进入“ secondState“,如下图所示:

Flow of states in the wrapper component

所以,问题是......

所以,问题是当用户到达流程的第三步时,即当他到达“secondState的“wrapperComponent”时有时second comp.”出现,有时不出现

迄今为止的调查结果......

在Adobe论坛中进行讨论:http://forums.adobe.com/message/4621058 3

经过两周的努力,我得出了半结论,不知何故,ActionScript中的事件内部流程停止了。

这意味着,当我的自定义组件“second comp.”未显示在屏幕上时:

  • 从“base state”到“secondState”的转换是 停止/暂停/停止,
  • 仅调度“second comp.”的某些事件 (“preinitialize”,“initialize”,“add”,“added”是 派遣)但其他一些不是:“addedToStage”和 “creationComplete”未发送。
  • activeEffects”和“base comp.”的变量“second comp.” “updateCompletePendingFlag”包含未播放的效果(例如 “RemoveChildActionInstance”或“AddChildActionInstance”)和
  • 这些变量“true”变量 组件的值是“baseState”,意味着它们还没有完成 更新。

丑陋黑客

我找到了一种绕过问题的非常可怕的方法,解决了这个问题:

  • 我设置了一个500ms的计时器,当状态必须从“secondState”更改为“base comp.”时(即,从上图中的步骤2到步骤3),计时器开始计数< / LI>
  • 当此计时器启动时,我会检查组件(即“second comp.”或“updateCompletePendingFlag”)是否有任何待处理效果或“true == { {1}}”。
  • 如果检查结果为true,则强制在该特定组件上调用validateDisplayList()方法。

代码与此类似:

...
if ( toState == STATE_SECOND ) {
var theTimer    : Timer = new Timer(500,1);
theTimer.stop();
theTimer.addEventListener(
TimerEvent.TIMER_COMPLETE, 
theTimer_complete_Hdl, 
false, 0, true
);
theTimer.start();

currentState = STATE_SECOND ;
}
...

计时器调用此函数:

private function theTimer_complete_Hdl(event:TimerEvent):void
{
if (secondComp.updateCompletePendingFlag)
{

secondComp.invalidateDisplayList();
secondComp.validateDisplayList();
secondComp.validateNow();
this.invalidateDisplayList();
this.validateDisplayList();


}
...
} 

问题...

这是非常脏,不优雅的代码。此外,它给我糟糕的用户体验,因为刷新屏幕需要一秒多的时间,而且运动也不是很快。

我的猜测是它会以某种方式对性能产生负面影响。

**有关可能发生的事情的任何想法或强制FlashPlayer继续播放效果而不是杀死它们并强制执行updateDisplayList的更好方法吗?**

谢谢你们!!! : - )

1 个答案:

答案 0 :(得分:0)

我认真地认为这是FlashPlayer的错误。

显然,最可能的答案是,这确实是我的错误。

我花了很多时间在这上面,不是因为它很难,而是因为项目很复杂,问题出在一个与问题不直接相关的课程中。

在查明原点之后,这是一个相当容易的修复。

导致问题的原因是什么?

我和myCustomComponent一起使用了之前状态中的另一个自定义类(即“base comp.”中的“base state”)。

customClass扩展了flex mx Label类。在commitProperties()重写方法中,它没有将标志设置为false,而是再次调用invalidateProperties()。当然,这是一个错误,并且在这个类中引发了一个无限循环(在“base comp.”组件中有五个实例。

这并不妨碍应用程序继续运行。它并没有停止它。但它阻止了从运行过渡中定义的效果和myCustomComponent实例完成创建。

base comp.”中出现错误的伪代码是这样的:

override protected function commitProperties():void
{
    super.commitProperties();
    if (somethingChanged)
    {
        //1: I wasn't setting somethingChanged=false

        //2: I needed to call invalidateProperties() again, like this:
        invalidateProperties();     
    }
}

正确的版本是:

override protected function commitProperties():void
{
    super.commitProperties();
    if (somethingChanged)
    {
        //1: I added this line:
        somethingChanged=false;

        //2: I still need to call invalidateProperties() again, like this:
        invalidateProperties();     
    }
}

甚至更好:

override protected function commitProperties():void
{
    if (somethingChanged)
    {
        //1: I added this line:
        somethingChanged=false;

        //2: Instead of invalidating the properties, doing some  
        //  processing and calling super.commitProperties()
        ...; //  (some processing)
    }
    super.commitProperties();       
}