2010-06-03 2 views
1

Я создал АС класса для использования в качестве модели данных, как показано здесь:Flex 4: Getter становится до того сеттер наборы

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> 

Проблема у меня в том, что функция добытчик работает, прежде чем loadXML закончил, так что XML varible в моем главном приложении появляется неопределенными в трассировки стека. В частности, функция loadXML называется ResultEvent.RESULT, а затем перескакивает на setXML и т. Д., Код в основном приложении продолжает выполняться, а loadXML ждет результата, поэтому getter в главном приложении (var xml: XML = model. xml;) выполняется до того, как переменная была определена setXML.

Как разместить условие где-нибудь, которое сообщает получателю, что до завершения функции loadXML() до запуска?

+0

Вы хотите использовать токен Async – phwd

ответ

0

Ваша модель должна расширять EventDispatcher и (с помощью настраиваемых событий) отправлять событие, указывающее, что модель была успешно загружена. Это необходимо, потому что Flex является асинхронным ...

Тогда в Application после создания модели просто добавить слушатель события к событию нагрузки, и там, где вы можете начать использовать модель вары

Дона» t забыть отправлять и слушать любые события ошибки!

НТН Гас

Что-то вроде этого ...

в главном приложении:

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

Спасибо за помощь, Гас, но это то место, где я застреваю. Я не уверен, как создать настраиваемое событие внутри функции model/loadXML и передать что-то обратно в основном приложении. У меня уже есть ResultEvent, который запускает функцию setXLM, но я не могу понять, как заставить его вернуть что-то из основного приложения. У вас есть код, который это делает? – Steve

+0

Перейдите по ссылке см., как работает диспетчеризация пользовательских событий. http://livedocs.adobe.com/flex/3/html/help.html?content=createevents_3.html Существуют три основных шага: 1.) Создайте свое настраиваемое событие (необязательно, вы можете повторно отобразить ResultEvent). 2.) установите метаданные для события. (Позволит MXML компилятор распознает событие) 3.) отправляет событие не забудьте переопределить EventDistpatcher здесь другие ссылки, которые могут помочь вам: http://bit.ly/9WlEWA HTTP: // liveocs.adobe.com/flex/3/langref/flash/events/EventDispatcher.html#includeExamplesSummary – Gus

+0

Строка: var modelEvent: ModelEvent = new ModelEvent (ModelEvent.LOADED); вызывает ошибку: «Позвоните, возможно, с неопределенным методом ...» Это кажется очень близким, и я пытаюсь настроить код, чтобы заставить его работать ... любая идея, почему это не будет распознано? Спасибо! – Steve

0

Это может быть просто опечатка в том, что вы вставили здесь, но

private function setXML(event:ResultEvent):void 

отсутствует пространство, что делает функцию setXML вместо settign переменной XML ... Это causeing ваш вопрос?

+0

Код выполняет тонкую трассировку и показывает, что переменные определены. Как я уже сказал, проблема в том, что функция, устанавливающая переменную, завершается ПОСЛЕ получения геттера, поэтому геттер становится нулевым. – Steve

1

Это должно работать, как я уже говорил в комментариях, вы должны использовать

асинхронных маркера Design Pattern 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.

+0

Спасибо за ссылку и информацию, но проблема не в настройщике. Переменная устанавливает штраф, но функция get выполняется до завершения фидера. Моя мысль заключалась бы в том, чтобы что-то вроде асинхронного токена в getter, но на нем нет триггера события. Возможно, мне придется использовать другой шаблон шаблона, чтобы дождаться установки установщика перед выполнением getter ... – Steve

+0

Мой плохой. :(... Вы можете попробовать отправить изменение события из setter dispatchEvent (новое событие (событие CHANGE)) и добавить прослушиватель событий к вашей модели до загрузки, например model.addEventListener (Event.CHANGE, set), где установлено это изменение булева и установка this._xml – phwd

0

Это будет работать как предусмотрено. Поскольку служба xml является асинхронным запросом, она отключает запрос, а затем продолжает оценивать шаги. В этом случае происходит вызов метода getter.

Итак, главное, чтобы вы не могли установить xml напрямую. У вас должен быть установлен объект xml после того, как результат будет возвращен. Это можно сделать, добавив к вашей модели прослушиватель событий, чтобы после того, как служба была возвращена, ваш основной пакет также будет уведомлен, или привязав значение xml между вашим основным пакетом и моделями xml.

+0

Не могли бы вы предоставить немного кода, чтобы проиллюстрировать это? Я пытался найти примеры этой концепции, но не могу понять, как заставить мой класс модели уведомлять основное приложение, которое оно готово. – Steve

0

Спасибо за помощь в этом, особенно Гас для ложной подачи мне этот отличный код и ссылки. Вот окончательный код, который я использовал для выполнения этого:

Основное приложение:

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

Я закончил с использованием стандартного класса событий (я думаю, не совсем уверен, почему это работает еще), и теперь код работает отлично. Любые дальнейшие мысли об этом будут оценены, но он работает!

Смежные вопросы