- 浏览: 185300 次
- 性别:
- 来自: 成都
文章分类
最新评论
-
java-007:
alanland 写道一楼还有个眉头没脑的提问你的理解能力真T ...
神奇的Grails:自关联的树状Domain一行代码获取所有子节点 -
xpjava:
请问大侠,如何显示?这个树形结构?
神奇的Grails:自关联的树状Domain一行代码获取所有子节点 -
谷赛玉:
我也遇到int和long不匹配的问题了,呵呵
iBatis访问MS Access数据库(*.mdb)时的若干注意事项 -
alanland:
一楼还有个眉头没脑的提问
神奇的Grails:自关联的树状Domain一行代码获取所有子节点 -
alanland:
涨知识了,还学到一个 flatten
神奇的Grails:自关联的树状Domain一行代码获取所有子节点
原文出自GWT-Presenter项目的创建者对该项目的简要介绍:gwt-presenter explained
NOTE: Feb 12, 2010: We have upgraded gwt-presenter to 1.1.1 from replace-branch, which has heavy impact on how we handle places. After reading this post, go to gwt-presenter upgrade and read about the place changes.
It took me quite some time browsing source code and examples to fully understand how gwt-presenter works. This will be a short walkthrough of how the framework works with some references to its source code. I will make references to source code classes that you can browse online here. I really want to give the developers of gwt-presenter big thumbs up for a great job. It is a great implementation and there seems to be even more improvements on the way.
Okey. So what is gwt-presenter really? It is a GWT implementation of the MVP pattern as described by Ray Ryan at Google I/O 2009. It also integrates support for history handling, event handling and GIN integration. GIN is a GWT framework for dependency injection which we will use in this project as well.
If you're not familiar with MVP, have a look here
Some good gwt-presenter guides/examples: gwt-presenter Getting Started , Apache HUPA project and TurboManage blog
We will take a look at the following concepts: Presenter, Display, Places and EventBus.
Let's have a quick look at how the Presenter and Display interfaces look.
public interface Presenter { void bind(); void unbind(); Display getDisplay(); void refreshDisplay(); void revealDisplay(); } public interface Display { void startProcessing(); void stopProcessing(); }
(注:该实现基于gwt-presenter1.0 版本)
When you implement your presenter, you can implement the Presenter interface directly but you will likely want to inherit from BasicPresenter or WidgetPresenter. WidgetPresenter inherits from BasicPresenter and only adds a Display interface via WidgetDisplay. But let's focus on BasicPresenter now since this is where the logic is. BasicPresenter adds the following abstract methods that you must implement:
protected abstract void onBind(); protected abstract void onUnbind(); public abstract Place getPlace(); protected abstract void onPlaceRequest( PlaceRequest request );
BasicPresenter implements bind(), unbind(), getDisplay() and revealDisplay() from Presenter interface, so you don't generally need to bother with those. Let's go over a typical scenario where we subclass BasicPresenter.
When you create your presenter, you must provide BasicPresenter with references to a Display implementation and a reference to the EventBus. The Display implementation will be your View. The EventBus is a gwt-presenter class that inherits from GWT HandlerManager, which is how GWT handles events. The eventbus has an important role in the MVP patterns as it makes it possible for us to really enforce loose coupling in our app. Our presenters and views that reside on the same abstraction layer should have no knowledge of each other. The only thing they care about are events. Who triggers the event and who handles it is not their concern.
Once you have created your presenter, you will want to call bind() on it before you use it in any way. This will give you a callback to onBind() in your presenter, where you typically setup event handlers etc for any user interaction that your corresponding view offers. BasicPresenter will also register a PlaceRequestHandler if you have defined a Place in your presenter. Typically you will do this for most of your presenters. The place string you provide is bascially the history token that will trigger this presenter to activate. You can however also trigger this manually via a PlaceRequestEvent, which is useful. You can also define parameters for your place. For example, if you have a ShowPersonPresenter you probably want to handle a Person with a specific id. You can then add id as a parameter and gwt-presenter will handle that for you.
When a place event is triggered that matches your presenter place token, you will get a callback in your presenter's onPlaceRequest(PlaceRequest request). This is where you typically do the real work by fetching the model data and updating the view with that data. Another nifty thing that happens when this event is handled is that revealDisplay() is called on your presenter. Unless you override this method, BasicPresenter will fire a PresenterRevealedEvent with your presenter as parameter. Once you start layering your app, you will have nested presenters. We will look at this later, but basically your parent presenter will get a callback that this presenter is active and should be displayed. It's all very automagic .
When you are "done" with the presenter, you call unbind() on it and BasicPresenter will remove all event handlers and give you a callback to onUnbind() where you basically undo what you did in onBind().
Okey. So let's have a look at how the Display interface interacts with your presenters and views. Remember earlier that we talked about WidgetPresenter and WidgetDisplay? These are the classes you will want to inherit from for your widget presenters/views. WidgetDisplay extends Display interface and adds a method asWidget(). This is necessary to actually use your widgets outside of the view class. So let's assume now that we are writing widget stuff and inherit from those classes.
You define all your presenter-view interaction in the Display interface, which you define in your presenter like this:
public interface Display extends WidgetDisplay { void setData(Data data); HasClickHandlers getEdit(); HasClickHandlers getDelete(); }
The above is just a typical example of how the interface might look. We have a method setData() to update our view with data, and two methods for getting the HasClickHandlers interface from user interaction elements in the view. These are often buttons which we will add ClickHandlers to in our presenters bind() method. You do something like this:
display.getDelete().addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { eventBus.fireEvent(new DeletePersonEvent("id of Person")); } });
Let's move on and have a look at our View, the Display implementation, which typically looks like this:
public class OurView extends Composite implements OurPresenter.Display { private VerticalPanel mPanel; private Button mSaveButton; private Button mCancelButton; public OurView(){ mPanel = new VerticalPanel(); mSaveButton = new Button(); mCancelButton = new Button(); mPanel.add(mSaveButton); mPanel.add(mCancelButton); initWidget(mPanel); } @Override public HasClickHandlers getCancel() { return mCancelButton; } @Override public HasClickHandlers getSave() { return mSaveButton; } @Override public void setData(Data data) { // Present the data } @Override public Widget asWidget() { return this; } @Override public void startProcessing() { } @Override public void stopProcessing() { }
The methods startProcessing and stopProcessing are mainly there for integration with gwt-dispatch. Anyway, the view above is pretty straightforward, so I will move on now.
Let's dig into the WidgetContainerPresenter and WidgetContainerDisplay classes. It is very likely that you will want to use these when you start layering your views. A WidgetContainerPresenter holds a list of other presenters. The main feature of this class is how it handles presenter visiblity. In the onBind()-method, it creates a PresenterRevealedHandler for each child presenter that you have added.
Remember earlier where we mentioned that BasicPresenter fires a PresenterRevealedEvent as a result of a PlaceRequestEvent? Well, this is where this is caught and handled. It's a really nifty feature, as we don't need to care about a parent presenters at all when we want to present a particular widget. We just place a request event, the widget presenter gets a callback, and then we will get revealDisplay() callbacks all the way to our top level presenter container.
For the particular presenter that catches the event, it first calls showPresenter(presenter) on the presenter that should be activated and requests its view to be displayed. Then it calls revealDisplay() which will lead to the same thing on the next level. Forget everything you learned doing Swing development .
WidgetContainerDisplay enforces some expected methods on the view:
public interface WidgetContainerDisplay extends WidgetDisplay { void addWidget( Widget widget ); void removeWidget( Widget widget ); void showWidget( Widget widget );
It is up to the view how many widgets it holds and how they will be layout.
The library also provides access to DeckPresenter and DeckDisplay which are slight simplied version of the above. It uses a DeckPanel to present widgets, which holds a number of widgets in memory but only displays one at a given time. I would probably recommend using the WidetContainer-variants for more flexibility and control, but these might be useful for certain simple scenarios.
If you are using GIN for dependency injection, gwt-presenter has some convenience functions you might want to use. In your GIN client module class, do something like this:
// Make sure to inherit from gwt-presenter AbstractPresenterModule public class YourClientModule extends AbstractPresenterModule { @Override protected void configure() { // Bind presenters and views // For generic views, we have to bind displays separately from // presenters to avoid binding them several times bindDisplay(ShowDataPresenter.Display.class, ShowDataView.class); bindDisplay(EditDataPresenter.Display.class, EditDataView.class); bindDisplay(ListModelsPresenter.Display.class, ListModelsView.class); // Bind presenters only bind(ShowPersonPresenter.class).in(Singleton.class); bind(EditPersonPresenter.class).in(Singleton.class); bind(ListTeamsPresenter.class).in(Singleton.class); bind(ListPlayersPresenter.class).in(Singleton.class); // For 1-1 mapping of presenter-view, we can use bindPresenter() bindPresenter(DynamicContentPresenter.class, DynamicContentPresenter.Display.class, DynamicContentView.class); bindPresenter(AppPresenter.class, AppPresenter.Display.class, AppView.class); } }
You can then simply add @Inject to your presenter constructors to inject your display implementations.
That was it for now. Comment..feedback?
发表评论
-
GWT + Maven开发常见问题及处理(持续更新中)
2010-03-27 01:55 19081.总是提示“The project 'XXX' does n ... -
GWT-Presenter发布1.1.1
2010-03-07 21:38 1082一直关注GWT-Presenter的进展情况,最近该项目发布了 ... -
MVP For GWT 系列资料转载十:Loading a default view on startup with gwt-presenter
2010-03-07 20:57 941源文转自:Loading a default view on ... -
MVP For GWT 系列资料转载九:Base presenter and view classes for gwt-presenter
2010-03-07 20:23 827源文转自:Base presenter and view cl ... -
MVP For GWT 系列资料转载八:Swapping DIVs technique for navigation with gwt-presenter
2010-03-07 20:18 857源文转自:Swapping DIVs technique fo ... -
MVP For GWT 系列资料转载七:How to show a “Loading…” pop-up in your GWT app
2010-03-07 20:14 725源文转自:How to show a “Loading…” p ... -
MVP For GWT 系列资料转载六:Unit testing with JDO PersistenceManager injected via Guice
2010-03-07 15:34 810源文转自:Unit testing with JDO Pers ... -
MVP For GWT 系列资料转载五:More on unit testing with an injected JDO PersistenceManager
2010-03-07 15:30 977源文转自:More on unit testing with ... -
MVP For GWT 系列资料转载四:Writing common test data services for gwt-dispatch with Guic
2010-03-07 15:23 977源文转自:Writing common test data s ... -
MVP For GWT 系列资料转载三:How to reduce startup time with gwt-presenter
2010-03-07 15:18 894源文转自:How to reduce startup time ... -
MVP For GWT 系列资料转载二:An MVP-compatible EnumListBox for GWT
2010-03-07 15:15 861源文转自:An MVP-compatible EnumList ... -
MVP For GWT 系列资料转载一:Quick note on using gwt-presenter’s ActionException
2010-03-07 15:07 1028源文转自:Quick note on using gwt-pr ... -
GWT MVP模式的UML图
2010-03-07 14:34 1919转自:http://www.nieleyde.org/Skyw ... -
透过GXT 的 Mail 示例,学习GXT 的 MVC结构
2009-11-21 15:59 4557基于GWT 的 GXT UI框架 (即EXT-GW ... -
GWT也能jQuery?没有想不到
2009-04-19 23:14 2064今天看到有人用jQuery实现Skype式的按钮效果,突然想到 ...
相关推荐
GWT-Developer-Plugin
里面东西很多,都是关于GWT-COMET的内容,实现gwt的服务器推技术,包括gwt-comet-examples-1.2.3:google官网上的Test实例;gwt-comet-1.2.3.jar:jar包,gwt-example:聊天实例源代码(.java的),gwt-event-source...
gwt-dev-plugin
gwt-user.jar 大小:2.86 MB
gwt代码调试插件gwt-dev-plugin-x86.msi,针对ie浏览器使用
gwt-windows-1.7.1.zipgwt-windows-1.7.1.zipgwt-windows-1.7.1.zipgwt-windows-1.7.1.zipgwt-windows-1.7.1.zipgwt-windows-1.7.1.zip
gwt-dev-windows.jar 大小:9.60 MB
gwt-servlet.jar 最新版,由于文件太大、不可以上传、有需要可以留言、整包分享给你、
gwt-servlet-2.3.0.jar
gwt-benchmark-viewer.jar
gwt-2.7.0.part2.rar 官网下载最新版,提供给大家使用
gwt-servlet-1.4.61.jar
gwt ext gwt-ext gwt-ex t学习必备资料gwt ext gwt-ext gwt-ex t学习必备资料gwt ext gwt-ext gwt-ex t学习必备资料gwt ext gwt-ext gwt-ex t学习必备资料gwt ext gwt-ext gwt-ex t学习必备资料gwt ext gwt-ext gwt-...
gwt - dev - firefox16 plugin
gwt-dev-plugin是GWT针对浏览器的安装插件,包含IE、FireFox、Chrome的。不需要的匆下,非学习文档
gwt-2.5.1—part1.rar part2:http://download.csdn.net/detail/u011029071/5992583
GWT-Dev_plugin firefox26 免费下载,GWT 火狐插件。GWT-Dev_plugin firefox26 版本
GWT-Ext 是基于 Google Web Toolkit(GWT)和 ExtJs 的功能强大的网页开发控件库。它非常适用于进行纯 Java 语言的富 Internet 应用的快速开发。本系列文章将详细讲解 GWT-Ext 的基本结构和功能特点,并通过代码示例...
最好的gwt-ext学习资料,适合初学者。