#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, который у меня есть?