如何:UiBinder + GWT MVP +多个独立显示区域
我正在使用 GWT MVP 和 UiBinder 创建带有 DockLayoutPanel 的应用程序。我希望南北码头是静态的,包含按钮和链接。我想要在中心和东码头的两个不同区域拥有动态视图。由于这些动态区域应该相互独立,因此我为每个动态显示区域设置不同的 ActivityMapper 和 ActivityManager;中心、东上、东下。
当应用程序加载时,如何独立初始化这3个不同的显示区域?如何在一个显示区域中从一个 Activity 切换到另一个 Activity 而不影响其他区域?
当我使用 PlaceController 的 goTo 从一个区域中的一个位置切换到另一个位置时,另一区域的 Activity 会停止。
五月天,请帮忙,五月天!
以下是我的一些代码:
AppViewImpl.ui.xml
<g:DockLayoutPanel styleName="{style.dockPanel}" unit="PX" width="975px" height="100%">
<!-- DOCK PANEL EAST -->
<g:east size="220">
<g:LayoutPanel styleName="{style.eastPanel}">
<g:layer left="0px" width="220px" top="0px" height="105px">
<g:SimpleLayoutPanel ui:field="topRightPanel"/>
</g:layer>
<g:layer left="0px" width="220px" top="110px" height="340px">
<g:InlineLabel styleName="{style.label}" text="ANOTHER DISPLAY AREA"/>
</g:layer>
</g:LayoutPanel>
</g:east>
<!-- DOCK PANEL NORTH -->
<g:north size="110">
<g:LayoutPanel styleName="{style.northPanel}">
<g:layer left="0px" width="755px" top="0px" height="105px">
<g:InlineLabel styleName="{style.label}" text="NORTH PANEL"/>
</g:layer>
</g:LayoutPanel>
</g:north>
<!-- DOCK PANEL SOUTH -->
<g:south size="20">
<g:LayoutPanel styleName="{style.southPanel}">
<g:layer left="0px" width="755px" top="0px" height="20px">
<g:InlineLabel styleName="{style.label}" text="SOUTH PANEL"/>
</g:layer>
</g:LayoutPanel>
</g:south>
<!-- DOCK PANEL CENTER -->
<g:center>
<g:SimpleLayoutPanel ui:field="mainPanel" />
</g:center>
</g:DockLayoutPanel>
MyModule.java
public class MyModule Implements EntryPoint {
private Place defaultPlace = new DefaultPlace("");
public void onModuleLoad() {
// Create ClientFactory using deferred binding so we can replace with
// different impls in gwt.xml
ClientFactory clientFactory = GWT.create(ClientFactory.class);
EventBus eventBus = clientFactory.getEventBus();
PlaceController placeController = clientFactory.getPlaceController();
// Start ActivityManager for the main widget with our ActivityMapper
ActivityMapper topRightActivityMapper = new TopRightActivityMapper(clientFactory);
ActivityManager topRightActivityManager = new ActivityManager(topRightActivityMapper, eventBus);
topRightActivityManager.setDisplay(clientFactory.getAppView().getTopRightPanel());
// Start ActivityManager for the main widget with our ActivityMapper
ActivityMapper mainActivityMapper = new AppActivityMapper(clientFactory);
ActivityManager mainActivityManager = new ActivityManager(mainActivityMapper, eventBus);
mainActivityManager.setDisplay(clientFactory.getAppView().getMainPanel());
// Start PlaceHistoryHandler with our PlaceHistoryMapper
AppPlaceHistoryMapper historyMapper = GWT .create(AppPlaceHistoryMapper.class);
PlaceHistoryHandler historyHandler = new PlaceHistoryHandler(historyMapper);
historyHandler.register(placeController, eventBus, defaultPlace);
RootLayoutPanel.get().add(clientFactory.getAppView());
// Goes to place represented on URL or default place
historyHandler.handleCurrentHistory();
new AppController(clientFactory);
}
}
AppController.java
public class AppController implements AppView.Presenter {
private ClientFactory clientFactory;
AppController(ClientFactory clientFactory){
this.clientFactory = clientFactory;
goTo(new TopRightAPlace(""));
}
@Override
public void goTo(Place place) {
clientFactory.getPlaceController().goTo(place);
}
}
TopRightAViewImpl.java
public class TopRightAViewImpl extends Composite implements TopRightAView {
interface Binder extends UiBinder<Widget, TopRightAViewImpl> {
}
private static final Binder binder = GWT.create(Binder.class);
private Presenter listener;
@UiField
Button button;
public TopRightAViewImpl() {
initWidget(binder.createAndBindUi(this));
}
@Override
public void setName(String name) {
button.setHTML(name);
}
@Override
public void setPresenter(Presenter listener) {
this.listener = listener;
}
@UiHandler("button")
void onButtonClick(ClickEvent event) {
listener.goTo(some other place);
}
}
I am using GWT MVP and UiBinder to create an app with a DockLayoutPanel. I want the north and south docks to be static, containing buttons and links. I want to have dynamic views in the center and two different areas of the east dock. As these dynamic areas should be independent of each other, I am setting up different ActivityMapper and ActivityManager's for each dynamic display area; center, east-top, and east-bottom.
How can I independently initialize these 3 different display areas when the application is loaded? How can I switch from one Activity to another in one display area without affecting the other areas?
When I use the the PlaceController's goTo to switch from one Place to another in one area, the other area's Activity is stopped.
Mayday, please help, mayday!
The following is some of my code:
AppViewImpl.ui.xml
<g:DockLayoutPanel styleName="{style.dockPanel}" unit="PX" width="975px" height="100%">
<!-- DOCK PANEL EAST -->
<g:east size="220">
<g:LayoutPanel styleName="{style.eastPanel}">
<g:layer left="0px" width="220px" top="0px" height="105px">
<g:SimpleLayoutPanel ui:field="topRightPanel"/>
</g:layer>
<g:layer left="0px" width="220px" top="110px" height="340px">
<g:InlineLabel styleName="{style.label}" text="ANOTHER DISPLAY AREA"/>
</g:layer>
</g:LayoutPanel>
</g:east>
<!-- DOCK PANEL NORTH -->
<g:north size="110">
<g:LayoutPanel styleName="{style.northPanel}">
<g:layer left="0px" width="755px" top="0px" height="105px">
<g:InlineLabel styleName="{style.label}" text="NORTH PANEL"/>
</g:layer>
</g:LayoutPanel>
</g:north>
<!-- DOCK PANEL SOUTH -->
<g:south size="20">
<g:LayoutPanel styleName="{style.southPanel}">
<g:layer left="0px" width="755px" top="0px" height="20px">
<g:InlineLabel styleName="{style.label}" text="SOUTH PANEL"/>
</g:layer>
</g:LayoutPanel>
</g:south>
<!-- DOCK PANEL CENTER -->
<g:center>
<g:SimpleLayoutPanel ui:field="mainPanel" />
</g:center>
</g:DockLayoutPanel>
MyModule.java
public class MyModule implements EntryPoint {
private Place defaultPlace = new DefaultPlace("");
public void onModuleLoad() {
// Create ClientFactory using deferred binding so we can replace with
// different impls in gwt.xml
ClientFactory clientFactory = GWT.create(ClientFactory.class);
EventBus eventBus = clientFactory.getEventBus();
PlaceController placeController = clientFactory.getPlaceController();
// Start ActivityManager for the main widget with our ActivityMapper
ActivityMapper topRightActivityMapper = new TopRightActivityMapper(clientFactory);
ActivityManager topRightActivityManager = new ActivityManager(topRightActivityMapper, eventBus);
topRightActivityManager.setDisplay(clientFactory.getAppView().getTopRightPanel());
// Start ActivityManager for the main widget with our ActivityMapper
ActivityMapper mainActivityMapper = new AppActivityMapper(clientFactory);
ActivityManager mainActivityManager = new ActivityManager(mainActivityMapper, eventBus);
mainActivityManager.setDisplay(clientFactory.getAppView().getMainPanel());
// Start PlaceHistoryHandler with our PlaceHistoryMapper
AppPlaceHistoryMapper historyMapper = GWT .create(AppPlaceHistoryMapper.class);
PlaceHistoryHandler historyHandler = new PlaceHistoryHandler(historyMapper);
historyHandler.register(placeController, eventBus, defaultPlace);
RootLayoutPanel.get().add(clientFactory.getAppView());
// Goes to place represented on URL or default place
historyHandler.handleCurrentHistory();
new AppController(clientFactory);
}
}
AppController.java
public class AppController implements AppView.Presenter {
private ClientFactory clientFactory;
AppController(ClientFactory clientFactory){
this.clientFactory = clientFactory;
goTo(new TopRightAPlace(""));
}
@Override
public void goTo(Place place) {
clientFactory.getPlaceController().goTo(place);
}
}
TopRightAViewImpl.java
public class TopRightAViewImpl extends Composite implements TopRightAView {
interface Binder extends UiBinder<Widget, TopRightAViewImpl> {
}
private static final Binder binder = GWT.create(Binder.class);
private Presenter listener;
@UiField
Button button;
public TopRightAViewImpl() {
initWidget(binder.createAndBindUi(this));
}
@Override
public void setName(String name) {
button.setHTML(name);
}
@Override
public void setPresenter(Presenter listener) {
this.listener = listener;
}
@UiHandler("button")
void onButtonClick(ClickEvent event) {
listener.goTo(some other place);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
GWT
Place
、PlaceController
和PlaceHistoryMapper
使您能够在应用程序中创建可添加书签的 URL,从而允许浏览器的后退按钮和书签作为一个整体工作会期望。这就是 GWTPlace
的设计目的。因此,在任何时间点在应用程序中激活多个Place
是没有意义的,因为整个应用程序只有一个 URL。PlaceController
的goTo()
方法会通知已注册的ActivityManager
,后者在收到 PlaceChangeEvent 后停止当前 Activity。我建议您不要对
DockLayoutPanel
东侧的两个区域使用Place
和PlaceChangeEvent
。使用Place
作为应用程序的主屏幕,它可能是DockLayoutPanel
的中心。当您需要时,为东侧的区域触发不同的GwtEvent
类型,可以是通用事件类型之一(即ValueChangeEvent
)或自定义事件类型已更新。您仍然可以在东边使用Activitie
,但您需要创建自己的ActivityManager
,这实际上并不难。您所要做的就是复制 GWT 的ActivityManager
,将其重命名,并将处理PlaceChangeEvent
和PlaceChangeRequestEvent
的方法名称替换为这些方法的名称处理您自己的事件。GWT
Place
s,PlaceController
, andPlaceHistoryMapper
enable you to create bookmarkable URLs within your application that allow the browser's back button and bookmarks to work as one would expect. This is what GWTPlace
s was designed for. Therefore it does not make sense to have more than onePlace
activated in an application at any point in time since you have one URL for the entire application.PlaceController
'sgoTo()
method does notify the registeredActivityManager
, which stops the current Activity upon receiving a PlaceChangeEvent.My suggestion for you is not to use
Place
s andPlaceChangeEvent
s for the two areas on the east side of yourDockLayoutPanel
. UsePlace
s for your application's main screen, which is probably the center of yourDockLayoutPanel
. Fire differentGwtEvent
types, either one of the generic event types (ie.ValueChangeEvent
) or a custom event type, for the areas on the east side when you need to have them updated. You could still useActivitie
s for the east side, but you would need to create your ownActivityManager
, which is actually not that hard. All you have to do is to copy GWT'sActivityManager
, rename it, and replace the names of methods that handlePlaceChangeEvent
s andPlaceChangeRequestEvent
s with those that handle your own events.你确定你真的想使用谷歌的 mvp 实现吗?使用 mvp4g 实现此机制非常简单。主模块将负责初始化主视图并提供重新加载动态区域的逻辑。我在两个大型项目中使用了这个框架,并且效果非常好。
Are you sure you really want to use google's mvp implementation? It's failry easy to implement this mechanism using mvp4g. The main module would be responsible for initializing main view and providing logic to reload dynamic areas. I used this framework in two large projects and works like a charm.