AppEvent class
AppEvent负责承载着信息,在controller和view之间。每个AppEvent对象都会有一个专门的EventType定义。AppEvent对象可以随意的通过setData方法,承载一个或多个datas。这样很有益于传递状态信息。当设置多个Datas的时候,我们就需要使用key-value键值对,把每个Data命名,以方便检索。
另外一个功能就是,可是使用setHistoryEvent方法,在设置AppEvent的历史事件。这就意味着,当一个事件被派发出去的时候,该之间就会被设置成历史事件。这一特性的设计,方便在dispatcher里查询历史事件。
EventType class
EventType是用来定义事件类型的,具体来说是给AppEvent起名子的。具有代表性的,我们会在AppEvents类里,定义一些列的静态fields,器field的类别就是EventType。下面,我们就在RSSReader项目,定义应用事件
- 新建package:com.danielvaughan.rssreader.client.mvc.events,新建类AppEvents
- 在AppEvents类里,定义两个EventType的fields
package com.danielvaughan.rssreader.client.mvc.events;
import com.extjs.gxt.ui.client.event.EventType;
public class AppEvents {
public static final EventType Init = new EventType();
public static final EventType Error = new EventType();
}
Controller class
Controller在应用里,承担着对事件响应和处理的角色。一个Controller在其构造函数里,必须注册EventTypes,才可以监听事件。registerEventTypes方法就是用通过传入EventType参数,完成注册过程!
- 新建package:com.danielvaughan.rssreader.client.mvc.controllers,在此包下,新建类AppController继承Controller
- 在构造函数里,完成事件注册
package com.danielvaughan.rssreader.client.mvc.controllers;
import com.danielvaughan.rssreader.client.mvc.events.AppEvents;
import com.extjs.gxt.ui.client.mvc.AppEvent;
import com.extjs.gxt.ui.client.mvc.Controller;
public class AppController extends Controller {
public AppController() {
registerEventTypes(AppEvents.Init);
registerEventTypes(AppEvents.Error);
}
@Override
public void handleEvent(AppEvent event) {
}
}
当继承抽象类Controller的时候,必须要实现handleEvent抽象方法。此方法是用来定义如何处理不同EventType的。
如果想要查询一个Controller是否可以处理某个专门的AppEvent的时候,可以使用canHandle方法。
响应一个事件的处理流程如下:
- 事件出入总的controller
- 然后将事件派发到具体的某一个子controller
- 将事件转发到view,等待后续的操作
- 将如上三步整合起来。
接下来,我们要在RSSReader项目实现,AppController的handleEvent方法。
- orverride handleEvent 方法
- 目前,我们不需要在Controller层处理任何的事件,只是将所有的事件转发到view层。因此,我们需要定义一个View
private com.extjs.gxt.ui.client.mvc.View appView;
- 随着View的定义,我们将所有的evet都转发到view里——实现一个forward的功能。
package com.danielvaughan.rssreader.client.mvc.controllers;
import com.danielvaughan.rssreader.client.mvc.events.AppEvents;
import com.extjs.gxt.ui.client.mvc.AppEvent;
import com.extjs.gxt.ui.client.mvc.Controller;
import com.extjs.gxt.ui.client.mvc.View;
public class AppController extends Controller {
private View appView;
public AppController() {
registerEventTypes(AppEvents.Init);
registerEventTypes(AppEvents.Error);
}
@Override
public void handleEvent(AppEvent event) {
forwardToView(appView, event);
}
}
View class
View是GXT MVC架构中一部分。负责提供用户接口——显示可视化组件,响应从Controller转发过来的事件,当然也负责响应用户操作所产生的事件(AppEvents),并将其派发到Dispatcher。
正如controllers一样,views也需要实现handleEvent方法。为了保持代码整洁易懂,最好针对每一个EventType去创建一个on<EventType>方法。
比如,如果我们想要处理Init的EventType 。我们需要在handleEvent里检查其EventType,并调用对应的处理方法onInit。
protected void handleEvent(AppEvent event) {
EventType eventType = event.getType();
if (eventType.equals(AppEvents.Init)) {
onInit(event);
}
}
接下来,我们在RSSReader项目里,实现View层的代码
- 新建package:com.danielvaughan.rssreader.client.mvc.views,在此包下,新建AppView继承View
- 别忘了,orverride handleEvent方法
package com.danielvaughan.rssreader.client.mvc.views;
import com.extjs.gxt.ui.client.mvc.AppEvent;
import com.extjs.gxt.ui.client.mvc.Controller;
import com.extjs.gxt.ui.client.mvc.View;
public class AppView extends View {
public AppView(Controller controller) {
super(controller);
}
@Override
protected void handleEvent(AppEvent event) {
}
}
- 注意,如上的构造函数的写法。其原因是View没有无参的,空方法体的构造函数!java基础啦
- 正如我们之前介绍的:注册了两个事件Init和Error,那么就要有对应的on<EventType>方法
private void onInit(AppEvent event) {}
private void onError(AppEvent event) {}
- 现在,要实现handleEvent方法里面具体的内容——根据EventType跳转到对应的处理方法。
@Override
protected void handleEvent(AppEvent event) {
EventType eventType = event.getType();
if (eventType.equals(AppEvents.Init)) {
onInit(event);
} else if (eventType.equals(AppEvents.Error)) {
onError(event);
}
}
- 最后,我们需要让AppController和AppView之间有关联。通过override Appcontroller的 initialize方法实现。这样当AppView里面的事件才会通过此关联操作,跳转到AppController中去!
package com.danielvaughan.rssreader.client.mvc.controllers;
import com.danielvaughan.rssreader.client.mvc.events.AppEvents;
import com.danielvaughan.rssreader.client.mvc.views.AppView;
import com.extjs.gxt.ui.client.mvc.AppEvent;
import com.extjs.gxt.ui.client.mvc.Controller;
import com.extjs.gxt.ui.client.mvc.View;
public class AppController extends Controller {
private View appView;
public AppController() {
registerEventTypes(AppEvents.Init);
registerEventTypes(AppEvents.Error);
}
@Override
public void handleEvent(AppEvent event) {
forwardToView(appView, event);
}
@Override
public void initialize() {
super.initialize();
appView = new AppView(this);
}
}
package com.danielvaughan.rssreader.client.mvc.views;
import com.danielvaughan.rssreader.client.mvc.events.AppEvents;
import com.extjs.gxt.ui.client.event.EventType;
import com.extjs.gxt.ui.client.mvc.AppEvent;
import com.extjs.gxt.ui.client.mvc.Controller;
import com.extjs.gxt.ui.client.mvc.View;
public class AppView extends View {
public AppView(Controller controller) {
super(controller);
}
@Override
protected void handleEvent(AppEvent event) {
EventType eventType = event.getType();
if (eventType.equals(AppEvents.Init)) {
onInit(event);
} else if (eventType.equals(AppEvents.Error)) {
onError(event);
}
}
private void onInit(AppEvent event) {
}
private void onError(AppEvent event) {
}
}
Dispatcher class
Dispatcher是一个单独的类——是一个单实例的对象,穿梭于整个应用。他有着static的方法用来转发AppEvent对象。一个Controller需要通过Dispatcher去注册,然后监听不同EventType的AppEvent。当一个AppEvent被派发的时候,就会根据先前注册监听的EventType去唤醒AppEvent。一个事件可以在程序的任何地方被唤醒,只是需要Dispatcher的forwardEvent方法。如下有四个forwardEvent方法的重载,方便用户调用。
Method | Description |
forwardEvent(AppEvent event) | 将现有的AppEvent派发出去。 |
forwardEvent(EventType eventType) | 根据EventType,会新建一个AppEvent,再派发出去。 |
forwardEvent(EventType eventType, java. lang.Object data) | 根据EventType新建AppEvent,作为一个载体,装载一个object,并派发出去。 |
forwardEvent(EventType eventType, java. lang.Object data, boolean historyEvent) | 根据EventType新建AppEvent,装载一个object。并标记的AppEvent是否是一个历史事件,最后派发出去。 |
除了上述static的方法之外,Dispatcher同样还有非静态的dispatch方法。当然功能上是相同的。实是上,这些static的forwardEvent方法就是调用那些非静态的dispatch方法。唯一不同的是,在这些非静态的dispach方法里,没有上述的第四个方法。
如果Dispatcher有多个controllers被注册了,那么他同样会唤醒所有的AppEvent,其顺序是按照当时注册的顺序执行。我们要注意到这一执行顺序,尤其是在Controller的handleEvent方法处理AppEvent的时候。
总结整个GXT MVC功能集
GXT MVC 的实现步骤如下:- 派发(Dispatcher)不同类型的EventType
- 监听 Dispatcher(派发器)
- 接收事件,处理事件
- 定义不同类型的AppEvent
- 程序处理:转发AppEvent到派发器
- 程序处理:用户操作,触发了事件
- 程序处理:将事件注册到Controllers里
- 程序处理:将Controllers注册到派发器里(Dispatcher)