`
flashcloud
  • 浏览: 188852 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

关于GWT-Presenter的简介

    博客分类:
  • GWT
阅读更多

原文出自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-dev-plugin-x86-对ie浏览器使用

    3. **UI构建**:GWT提供了丰富的Widget库,允许开发者构建复杂的用户界面,同时支持MVP(Model-View-Presenter)和MVVM(Model-View-ViewModel)设计模式。 4. **国际化和本地化**:GWT支持多语言应用,可以轻松地...

    gwt-ext-选课系统

    在开发过程中,GWT-EXT选课系统可能会采用MVP(Model-View-Presenter)架构模式,将业务逻辑、视图展示和数据处理分离,提高代码的可维护性和测试性。同时,GWT的事件处理机制使得组件之间的交互更加灵活。 EXTdata...

    gwt-2.8.2 SDK 最新下载 google web toolkit

    2. **MVP模式**:Model-View-Presenter(MVP)是GWT推荐的开发模式。模型层处理业务逻辑,视图层负责用户界面展示,而presenter作为模型和视图之间的桥梁,协调两者通信。这种模式有利于代码组织和测试。 3. **国际...

    jqm4gwt-standalone-1.3.5.zip

    GWT提供了丰富的API和工具,支持MVP(Model-View-Presenter)架构,便于进行单元测试和代码调试。 **jqm4gwt与jQuery Mobile的集成** jqm4gwt-standalone-1.3.5.zip包含的jqm4gwt-master文件可能是该项目的源代码...

    gwt-polymer-sample:使用 gwt-polymer 存储库的示例

    1. **GWT 简介**:GWT 是一个开源的 Java 开发框架,用于构建高性能的、跨浏览器的富客户端 Web 应用。它允许开发者使用 Java 语言编写前端代码,并自动将其编译成 JavaScript,确保在多个浏览器上兼容。 2. **编译...

    GWT-Airline-scheduler:PSU高级Java项目5

    - **Model-View-Presenter (MVP)模式**: MVP是GWT推荐的架构模式,其中Model负责数据存储,View负责UI展示,Presenter作为Model和View之间的桥梁,处理用户交互和数据更新。 - **Remote Procedure Call (RPC)**: ...

    gwt-basics:测试新 GWT 功能的 GWT 基础知识

    通过学习和实践这个项目,开发者可以掌握GWT的基本概念,为进一步探索GWT的高级特性,如 MVP(Model-View-Presenter)架构、GWT Gin、GWT Elemental 或者GWT React等铺平道路。对于Java开发者来说,GWT提供了一条...

    gwt 揭秘 源码

    1. **GWT简介** GWT最初由Google开发,允许开发者使用Java语言编写客户端应用,然后通过编译器将其转换为优化过的JavaScript代码,运行在浏览器环境中。这种方式避免了直接编写JavaScript的复杂性,同时利用了Java...

    网页表格组件 GWT Advanced Table

    - **MVP(Model-View-Presenter)模式**:GWT推荐使用MVP模式进行开发,以分离业务逻辑和视图逻辑。 在压缩包中,`.classpath`、`.project`文件是Eclipse项目配置文件,用于设置项目构建路径和依赖。`GWT-Advanced-...

    GWT入门和进阶

    此外,MVP(Model-View-Presenter)模式是GWT中推荐的架构模式,它分离了用户界面、视图逻辑和业务逻辑。 **5. RPC通信** GWT提供了Remote Procedure Call (RPC)机制,使得客户端和服务器之间可以进行安全的数据...

    GWT 配置

    然而,GWT还有更多高级特性,如 Gin for dependency injection, GWT-RPC for server communication, RequestFactory for client-server communication, MVP (Model-View-Presenter)架构等,这些都是提升GWT应用功能...

    GWT

    例如,可能是关于性能优化、调试工具的使用,或者是GWT与其他工具集成的最佳实践。 总之,GWT是一个强大的开发框架,它简化了富互联网应用程序的开发,使Java开发者能够在浏览器环境中充分利用Java的便利性。通过...

    gwt文档整理

    1. **GWT简介** GWT的核心理念是利用Java语言进行Web应用开发,然后通过编译器将Java代码转换为优化过的JavaScript,从而在各种浏览器上运行。这种方式让开发者可以利用熟悉的Java环境和强大的Java库,同时避免了...

    GWT eclipse插件4.2版本离线下载包

    安装完成后,你就可以在Eclipse中创建新的GWT项目,利用GWT的特性,如MVP模式(Model-View-Presenter)、RPC(Remote Procedure Call)通信、以及丰富的用户界面组件库等,进行Web应用的开发。 总的来说,这个离线...

    利用GWT控制创建一个表

    - GWT是基于MVP(Model-View-Presenter)设计模式的,它提倡分离关注点,提高代码的可维护性和可测试性。 - GWT项目通常由`EntryPoint`类开始,它是应用的入口点,负责初始化和加载界面。 2. **创建表格组件**: ...

    gwt学习资料和实例项目

    **Tutorial-hellomvp-2.1.zip** MVP(Model-View-Presenter)是GWT中推荐的一种设计模式,用于组织和分离业务逻辑和用户界面。这个教程可能专注于介绍如何在GWT中实现MVP模式,帮助开发者理解如何划分模型、视图和...

    GWT进阶教程

    2. **GWT MVP模式**:Model-View-Presenter模式是一种常见的GWT应用架构,有助于分离视图、模型和逻辑,提升代码可维护性。 3. **GWT RAPID-UI**:GWT的Rapid-UI技术,如Cell Widgets,使开发者能快速构建动态表格...

    gwt参考文档

    这份“gwt参考文档”包含了关于GWT的详细技术信息,对于学习和掌握GWT技术至关重要。 一、GWT的基本概念与特点 1. **Java到JavaScript的编译**:GWT的核心特性之一是将Java代码转换为高效的JavaScript,这使得开发...

Global site tag (gtag.js) - Google Analytics