【问题标题】:Flex 4: Getter getting before setter setsFlex 4:在 setter 集合之前获取 getter
【发布时间】:2010-06-03 21:11:54
【问题描述】:

我创建了一个 AS 类用作数据模型,如下所示:

package
{   
    import mx.controls.Alert;
    import mx.rpc.events.FaultEvent;
    import mx.rpc.events.ResultEvent;
    import mx.rpc.http.HTTPService;

    public class Model
    {

        private var xmlService:HTTPService;
        private var _xml:XML;
        private var xmlChanged:Boolean = false;

        public function Model()
        {
        }

        public function loadXML(url:String):void
        {
            xmlService = new HTTPService();
            if (!url)
                xmlService.url = "DATAPOINTS.xml";
            else
                xmlService.url = url;

            xmlService.resultFormat = "e4x";        
            xmlService.addEventListener(ResultEvent.RESULT, setXML);
            xmlService.addEventListener(FaultEvent.FAULT, faultXML);
            xmlService.send();              
        }

        private function setXML(event:ResultEvent):void
        {
            xmlChanged = true;
            this._xml = event.result as XML;
        }

        private function faultXML(event:FaultEvent):void
        {
            Alert.show("RAF data could not be loaded.");
        }

        public function get xml():XML
        {
            return _xml;
        }           

    }
}

在我的主应用程序中,我正在启动应用程序并调用 loadXML 函数来获取 XML:

<fx:Script>
    <![CDATA[
        import mx.containers.Form;
        import mx.containers.FormItem;
        import mx.containers.VBox;
        import mx.controls.Alert;
        import mx.controls.Button;
        import mx.controls.Label;
        import mx.controls.Text;
        import mx.controls.TextInput;

        import spark.components.NavigatorContent;

        private function init():void
        {   
            var model:Model = new Model();
            model.loadXML(null);
            //the following line executes before model.loadXML has finished...
            var xml:XML = model.xml;
        }   

    ]]>
</fx:Script>

我遇到的问题是 getter 函数在 loadXML 完成之前正在运行,因此我的主应用程序中的 XML 变量在堆栈跟踪中出现未定义。具体来说,loadXML函数调用ResultEvent.RESULT,然后跳转到setXML等……主app中的代码继续执行,而loadXML等待结果,所以主app中的getter(var xml:XML = model. xml;) 在 setXML 定义变量之前执行。

如何在此处设置一个条件,告诉 getter 等到 loadXML() 函数完成后再运行?

【问题讨论】:

  • 你想使用异步令牌

标签: xml apache-flex actionscript


【解决方案1】:

这应该像我在 cmets 中所说的那样工作,你应该使用

异步完成令牌设计模式 Flex/AS 不会同步调用。

    public function loadXML(url:String):void
    {
        xmlService = new HTTPService();
        if (!url)
            xmlService.url = "DATAPOINTS.xml";
        else
            xmlService.url = url;

        xmlService.resultFormat = "e4x";        
        xmlService.addEventListener(ResultEvent.RESULT, setXML);
        xmlService.addEventListener(FaultEvent.FAULT, faultXML);
        var xmlCall:Object = xmlService.send();
        xmlCall.name = "SET";              
    }

    private function setXML(event:ResultEvent):void
    {
        var xmlCall:Object = event.token; // Asynchronous Completion Token

        if(xmlCall.name == "SET"){
            xmlChanged = true;
            this._xml = event.result as XML;
        }
        else {
        // not ready to set
        }
    }

您可以阅读设计模式here

【讨论】:

  • 感谢您的链接和信息,但问题不在于二传手。变量设置良好,但 get 函数在 setter 完成之前执行。我的想法是将诸如异步令牌之类的东西放在getter中,但是上面没有事件触发器。在执行 getter 之前,我可能需要使用不同的设计模式来等待 setter 设置...
  • 我的错。 :( ...您可以尝试从设置器 dispatchEvent(new Event(Event.CHANGE) ); 分派事件更改;并在加载之前向模型添加事件侦听器,例如 model.addEventListener(Event.CHANGE, set) where set是更改布尔值并设置 this._xml
【解决方案2】:

您的模型应该扩展 EventDispatcher 并(使用自定义事件)调度一个指示模型已成功加载的事件。这是必需的,因为 Flex 是异步的...

然后在创建模型后的应用程序中,只需将事件侦听器添加到加载事件中,就可以开始使用模型变量了

不要忘记调度和监听任何错误事件!

HTH 格斯

这样的……

在主应用程序中:

var model:Model = new Model();
// registering the listener
model.addEventListener(ModelEvent.LOADED, model_loadedHandler);
model.loadXML(null);

然后是听者

private function model_loadedHandler (event:ModelEvent):void
{
    var xml:XML = model.xml;
}

最后,在模型中:

private function setXML(event:ResultEvent):void
{
    xmlChanged = true;
    this._xml = event.result as XML;
    var modelEvent:ModelEvent = new ModelEvent(ModelEvent.LOADED); 
    // you can add other info to the event like the XML
    dispatch(modelEvent);
}

【讨论】:

  • 感谢您的帮助,Gus,但这是我卡住的地方。我不确定如何在模型类/loadXML 函数中创建自定义事件并将其传递回主应用程序。我已经有一个触发 setXLM 函数的 ResultEvent,但我不知道如何让它返回主应用程序的内容。你有一些代码可以做到这一点吗?
  • 点击链接查看自定义事件的调度是如何工作的。 livedocs.adobe.com/flex/3/html/… 有三个基本步骤:1.) 创建您的自定义事件(可选,您可以重新分配 ResultEvent)。 2.) 设置事件的元数据。 (将允许 MXML 编译器识别事件) 3.)调度事件不要忘记覆盖 EventDistpatcher 这里有其他链接可以帮助你:bit.ly/9WlEWAlivedocs.adobe.com/flex/3/langref/flash/events/…
  • 行:var modelEvent:ModelEvent = new ModelEvent(ModelEvent.LOADED);导致错误:“调用可能未定义的方法......”这感觉非常接近,我一直在尝试调整代码以使其工作......知道为什么这不会被识别吗?谢谢!
  • 您必须创建一个扩展 Event 的 ModelEvent 类,在那里您定义一个名为 LOADED 的静态常量(例如),它标识 XML 的负载。检查我之前提供的关于自定义事件的 livedocs 链接
【解决方案3】:

这可能只是您在此处粘贴的内容有误,但是

private function setXML(event:ResultEvent):void

缺少一个空格,创建一个 setXML 函数而不是 settign 一个 XML 变量...这是导致您的问题的原因吗?

【讨论】:

  • 代码执行良好,堆栈跟踪显示变量已定义。正如我所说,问题在于设置变量的函数在 getter 执行后完成,因此 getter 出现 null。
【解决方案4】:

这将按设计工作。由于 xml 服务是一个异步请求,它会触发请求,然后继续评估步骤。在这种情况下继续调用 getter 方法。

所以主要看的是不能直接设置xml。返回结果后,您必须设置 xml 对象。您可以通过向模型添加事件侦听器来做到这一点,以便在返回服务后也会通知您的主包,或者通过在主包和模型 xml 之间绑定 xml 值。

【讨论】:

  • 您能提供一些代码来说明这一点吗?我一直试图找到这个概念的例子,但不知道如何让我的模型类通知主应用程序它已经准备好。
【解决方案5】:

感谢您在这方面提供的所有帮助,尤其是 Gus 用勺子喂给我这么棒的代码和链接。这是我用来执行此操作的最终代码:

主应用:

<fx:Script>
    <![CDATA[
        import flash.events.Event;

        import mx.containers.Form;
        import mx.containers.FormItem;
        import mx.containers.VBox;
        import mx.controls.Alert;
        import mx.controls.Button;
        import mx.controls.Label;
        import mx.controls.Text;
        import mx.controls.TextInput;

        import spark.components.NavigatorContent;

        private var model:Model = new Model();

        private function init():void
        {   
            model.addEventListener(Event.COMPLETE, model_loadedHandler);
            model.loadXML(null);
        }

        private function model_loadedHandler (e:Event):void
        {
            var xml:XML = model.xml;
            var sectorList:XMLList = xml.SECTOR;
            trace(sectorList);
            }               

        }

    ]]>
</fx:Script>

还有 Model.as:

package
{   
    import flash.events.Event;
    import flash.events.EventDispatcher;

    import mx.controls.Alert;
    import mx.rpc.AsyncToken;
    import mx.rpc.events.FaultEvent;
    import mx.rpc.events.ResultEvent;
    import mx.rpc.http.HTTPService;


    public class Model extends EventDispatcher
    {
        private var xmlService:HTTPService;
        private var _xml:XML;

        public function loadXML(url:String):void
        {
            xmlService = new HTTPService();
            if (!url)
                xmlService.url = "DATAPOINTS.xml";
            else
                xmlService.url = url;

            xmlService.resultFormat = "e4x";                
            xmlService.addEventListener(ResultEvent.RESULT, setXML);
            xmlService.addEventListener(FaultEvent.FAULT, faultXML);            
            xmlService.send();
        }

        private function setXML(event:ResultEvent):void
        {
            this._xml = event.result as XML;
            var modelEvent:Event = new Event(Event.COMPLETE);
            //var modelEvent:ModelEvent = new ModelEvent(ModelEvent.LOADED); 
            dispatchEvent(modelEvent);


            //this._xml = event.result as XML;
        }

        private function faultXML(event:FaultEvent):void
        {
            Alert.show("RAF data could not be loaded.");
        }

        public function get xml():XML
        {
            return _xml;
        }
    }
}

我最终使用了一个标准的事件类(我想,还不完全确定为什么会这样),现在代码运行良好。对此有任何进一步的想法将不胜感激,但它正在运行!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-23
    • 2012-01-24
    • 2020-02-09
    • 2019-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多