Flex 4:Getter在setter设置之前获得

时间:2010-06-03 21:11:55

标签: xml flex actionscript

我创建了一个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 varible在堆栈跟踪中未定义。具体来说,loadXML函数调用ResultEvent.RESULT,然后跳转到setXML等...主应用程序中的代码继续执行而loadXML等待结果,因此主应用程序中的getter(var xml:XML = model。 xml;)在setXML定义变量之前执行。

如何在这里放置条件告诉getter等到loadXML()函数在运行之前完成?

5 个答案:

答案 0 :(得分:1)

这应该像我在评论中所说的那样使用

异步完成令牌设计模式 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

答案 1 :(得分:0)

这可能只是你在这里粘贴的印刷错误

private function setXML(event:ResultEvent):void

缺少一个空格,制作一个setXML函数而不是settign一个XML变量......这会导致你的问题吗?

答案 2 :(得分:0)

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

所以要注意的主要是你不能直接设置xml。返回结果后,必须设置xml对象。您可以通过向模型添加事件侦听器来执行此操作,以便在返回服务后,也会通知主程序包,或者通过绑定主程序包和模型xml之间的xml值。

答案 3 :(得分:0)

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

然后在创建模型后的应用程序中,只需将事件监听器添加到load事件,然后在那里可以开始使用模型变量

不要忘记发送和收听任何错误事件!

HTH 格斯

像这样......

主app中的

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);
}

答案 4 :(得分:0)

感谢您对此提供的所有帮助,特别是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;
        }
    }
}

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