Flex 4.5 не прослушивает пользовательское событие, отправленное в пользовательском КАЧЕСТВЕ класса

#actionscript-3 #apache-flex #events

#actionscript-3 #apache-flex #Мероприятия

Вопрос:

У меня следующая ситуация:

У меня есть обработчик событий, который отображает небольшие сообщения в строке состояния моего приложения. Эти сообщения проходят путем отправки событий из пользовательских компонентов. Простое сообщение может быть похоже на «HTTP Error» или около того.

Теперь основной прослушиватель событий в главном файле приложения прослушивает событие, отправленное любым пользовательским компонентом, но, похоже, отказывается прослушивать события, отправленные пользовательским КАК классы.

Вот мой код для пользовательского события:

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

    public class ShowNoticeEvent extends Event
    {
        public var message:String;
        public static const SHOW_NOTICE:String = "showNotice";

        public function ShowNoticeEvent(type:String, msg:String, bubbles:Boolean = false, cancelable:Boolean = false)
        {
            super(type, bubbles, cancelable);
            this.message = msg;
        }

        override public function clone():Event
        {
            return new ShowNoticeEvent(type, message);
        }
    }
}
  

Это прослушиватель событий в главном файле приложения:

 addEventListener(ShowNoticeEvent.SHOW_NOTICE, showNoticeListener, true);
  

И это пользовательский класс AS, который отправляет пользовательское событие. Я вставил весь код, чтобы вы могли видеть всю его часть.

    package components.dashboard
{
    import components.dashboard.models.*;

    /* Event imports */
    import flash.events.*;
    import main.events.*;

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

    [Event(name="showNotice", type="main.events.ShowNoticeEvent")]
    public class Controller extends UIComponent
    {
        private var baseUrl:String;

        public function Controller(baseUrl:String)
        {
            this.baseUrl = baseUrl;
        }

        public function getRunningQuotations():void
        {
            var runningQuotationsList:RunningQuotationsList = RunningQuotationsList.getInstance();

            execService("index.php?a=1", runningQuotationsList.updateList, "pnlRunningQuotations"); 
        }

        public function getRecentProjects():void
        {
            var recentProjectsList:RecentProjectsList = RecentProjectsList.getInstance();

            execService("index.php?a=2", recentProjectsList.updateList, "pnlRecentProjects");
        }

        public function getLatestCustomers():void
        {
            var latestCustomersList:LatestCustomersList = LatestCustomersList.getInstance();

            execService("index.php?a=3", latestCustomersList.updateList, "pnlLatestCustomers");
        }

        private function execService(url:String, listener:Function, component:String):void
        {
            var basicService:HTTPService = new HTTPService(baseUrl);
            basicService.showBusyCursor = true;
            basicService.addEventListener(FaultEvent.FAULT, function(e:FaultEvent):void{httpFault(e, component)});
            basicService.method = "POST";
            basicService.resultFormat = "text";
            basicService.url = url;
            basicService.addEventListener(ResultEvent.RESULT, listener);
            basicService.send();            
        }

        private function httpFault(event:FaultEvent, component:String = null):void {
            var faultstring:String = event.fault.faultString;
            var eventObj:ShowNoticeEvent = new ShowNoticeEvent(ShowNoticeEvent.SHOW_NOTICE, faultstring, true); 

            dispatchEvent(eventObj);
            trace(faultstring);
        }
    }
}
  

Итак, подведем итог:
— Прослушиватель событий прослушивает пользовательское событие, отправленное любым пользовательским компонентом.
— Прослушиватель событий не прослушивает пользовательское событие, отправленное классом AS.

Те, кому интересно, событие действительно отправляется, вот почему я добавил вызов трассировки.

Комментарии:

1. Ваш вопрос «Почему мой обработчик событий не выполняет код?» Или что-то еще? Добавили ли вы класс контроллера в качестве дочернего элемента в какой-либо контейнер, который находится в списке отображения? Если нет; события не будут отображаться.

2. Да и нет, обработчик событий выполняет код только тогда, когда событие отправляется из дочернего компонента, но не тогда, когда оно отправляется из класса AS. Класс контроллера не является дочерним для какого-либо контейнера из списка отображения, поэтому он не будет всплывать. Я не думаю, что смогу сделать его дочерним, или я мог бы в этом случае, но тогда я не смог бы сделать это с моими моделями, они не являются дочерними ни от чего, я думаю?

3. Вам следует обратить внимание на Robotlegs для лучшего способа обработки связи между вашими классами. Класс контроллера не должен быть представлением (которым является любой класс, расширяющий UIComponent), и поэтому он не должен иметь возможности отправлять события против самого списка отображения. Не говоря уже о том, что это класс обслуживания, а вовсе не класс контроллера. Возможно, вы захотите потратить некоторое время на AS3DP.com чтобы понять, как использовать шаблоны проектирования для достижения ваших целей, а не жестко связывать ваш код с помощью одиночных элементов tinyurl.com/4qq53yj

4. Я только сделал это расширением UIComponent, потому что я не мог отправлять события, только когда я расширил этот класс. И да, я знаю о том факте, что это на самом деле скорее класс модели / сервиса, чем класс контроллера, я работаю над тем, чтобы поместить весь mxml В виде кода в класс контроллера и поместить код currentcontroller в модели. Я не вижу никаких одиночек в моем code atm? Но я прочитаю предоставленные вами документы, спасибо.

5. Вы можете расширить EventDispatcher, чтобы иметь возможность отправлять события (или реализовать IEventDispatcher). В вашем коде RecentProjectsList.getInstance() воняет до небес, как синглтон. Просто говорю.

Ответ №1:

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

выполнив

 addEventListener(ShowNoticeEvent.SHOW_NOTICE, showNoticeListener, true);
  

в основном файле вы добавляете прослушиватель на сцену.

Итак, в основном вы делаете.

 stage.addEventListener(ShowNoticeEvent.SHOW_NOTICE, showNoticeListener, true);
  

Если экземпляр контроллера отсутствует на сцене, вы не увидите событие.

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

Комментарии:

1. stage.dispatchEvent просто дает мне нулевую ссылку… Как бы я использовал этот шаблон одноэлементного типа? Я знаю, что это такое, но я просто не вижу смысла в этом случае, не могли бы вы направить меня на правильный путь?

2. У одиночек нет приемлемого варианта использования misko.hevery.com/code-reviewers-guide /…

3. @mortana Вы превращаете класс контроллера в одноэлементный. По сути, у вас есть только один глобальный экземпляр класса. Вы можете подключить к нему всех своих слушателей.

4. @Amy вопреки этому обзору, проблема этого вопроса ориентирована на глобальные события, и это идеально подходит для синглтона.

5. Да, синглтон в нижнем регистре (только один в программе, например, шина событий RobotLegs), но не синглтон с большой буквы S (глобальное состояние, доступное отовсюду через статическое свойство). Глобальное состояние — это быстрый путь к недостижимому беспорядку, который вы не сможете переписать, как только поймете, в какой ужасный беспорядок вы попали. У Google даже есть детектор одноэлементных элементов, чтобы находить их и выявлять.

Ответ №2:

Главная:

 Controller.getLastInstance().addEventListener(ShowNoticeEvent.SHOW_NOTICE, showNoticeListener, true)
  

.

 package components.dashboard
{
    import components.dashboard.models.*;

    /* Event imports */
    import flash.events.*;
    import main.events.*;

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

    [Event(name="showNotice", type="main.events.ShowNoticeEvent")]
    public class Controller extends UIComponent
    {
        static public function getLastInstance():Controller { return _instance; }
        static private var _instance:Controller;
        private var baseUrl:String;

        public function Controller(baseUrl:String)
        {
            _instance = this;
            this.baseUrl = baseUrl;
        }

        public function getRunningQuotations():void
        {
            var runningQuotationsList:RunningQuotationsList = RunningQuotationsList.getInstance();

            execService("index.php?a=1", runningQuotationsList.updateList, "pnlRunningQuotations"); 
        }

        public function getRecentProjects():void
        {
            var recentProjectsList:RecentProjectsList = RecentProjectsList.getInstance();

            execService("index.php?a=2", recentProjectsList.updateList, "pnlRecentProjects");
        }

        public function getLatestCustomers():void
        {
            var latestCustomersList:LatestCustomersList = LatestCustomersList.getInstance();

            execService("index.php?a=3", latestCustomersList.updateList, "pnlLatestCustomers");
        }

        private function execService(url:String, listener:Function, component:String):void
        {
            var basicService:HTTPService = new HTTPService(baseUrl);
            basicService.showBusyCursor = true;
            basicService.addEventListener(FaultEvent.FAULT, function(e:FaultEvent):void{httpFault(e, component)});
            basicService.method = "POST";
            basicService.resultFormat = "text";
            basicService.url = url;
            basicService.addEventListener(ResultEvent.RESULT, listener);
            basicService.send();            
        }

        private function httpFault(event:FaultEvent, component:String = null):void {
            var faultstring:String = event.fault.faultString;
            var eventObj:ShowNoticeEvent = new ShowNoticeEvent(ShowNoticeEvent.SHOW_NOTICE, faultstring, true); 

            dispatchEvent(eventObj);
            trace(faultstring);
        }
    }
}
  

Не идеально, поскольку у вас может быть только 1 из них.
Но я думаю, что лучше, чем превращать простой EventDispatcher в DisplayObject и добавлять его в stage, чтобы просто всплывать.

Комментарии:

1. Это наверняка не было бы идеальным решением, поскольку тогда я должен делать это для каждого класса AS, который у меня есть?