Activities and Places es la implementación de google del patrón MVP. Si bien es posible desarrollar páginas web estáticas utilizando Activities and Places, en la versión GWT 2.3 no hay suficiente información sobre su integración con el servidor si se puede utilizar RPC o RequestFactory. Este último requiere la clase com.google.web.bindery.event.shared.EventBus pero el ejemplo a continuación sólo funciona con com.google.gwt.event.shared.EventBus. En un desarrollo real se recomienda utilizar RequestFactory y el paquete com.google.web.bindery.event.shared ya que funciona con Aplicaciones GWT y Android.
De acuerdo al Google I/O 2011 recomiendan utilizar GWTP, RequestFactory y Objectify para el desarrollo de aplicaciones.
El ejemplo a continuación es solo para dar una idea del funcionamiento del MVP. El código fuente lo puede descargar aqui.
La estructura de la pagina web sería la siguiente:
Dentro del paquete client crear la interfaz ClientFactory y su implementación
package com.paginaweb.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.Window; public class PaginaWeb implements EntryPoint { public void onModuleLoad() { Window.alert("Hola Mundo"); } }
Su implementación
package com.paginaweb.client; import com.google.gwt.event.shared.EventBus; import com.google.gwt.event.shared.SimpleEventBus; import com.google.gwt.place.shared.PlaceController; public class ClientFactoryImpl implements ClientFactory { private static final EventBus eventBus = new SimpleEventBus(); private static final PlaceController placeController = new PlaceController(eventBus); @Override public EventBus getEventBus() { return eventBus; } @Override public PlaceController getPlaceController() { return placeController; } }
Agrego unas lineas al EntryPoint
package com.paginaweb.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.client.GWT; import com.google.gwt.event.shared.EventBus; import com.google.gwt.place.shared.PlaceController; import com.google.gwt.user.client.Window; public class PaginaWeb implements EntryPoint { public void onModuleLoad() { ClientFactory clientFactory = GWT.create(ClientFactory.class); EventBus eventBus = clientFactory.getEventBus(); PlaceController placeController = clientFactory.getPlaceController(); } }
Dentro del paquete mvp se crean 2 archivos AppActivityMapper.java y AppPlaceHistoryMapper.java
package com.paginaweb.client.mvp; import com.google.gwt.activity.shared.Activity; import com.google.gwt.activity.shared.ActivityMapper; import com.google.gwt.place.shared.Place; import com.paginaweb.client.ClientFactory; public class AppActivityMapper implements ActivityMapper { private ClientFactory clientFactory; public AppActivityMapper(ClientFactory clientFactory) { this.clientFactory = clientFactory; } @Override public Activity getActivity(Place place) { // TODO Auto-generated method stub return null; } }
la interfaz AppPlaceHistoryMapper
package com.paginaweb.client.mvp; import com.google.gwt.place.shared.PlaceHistoryMapper; public interface AppPlaceHistoryMapper extends PlaceHistoryMapper { }
Modificar el archivo del modulo PaginaWeb.gwt.xml
<?xml version="1.0" encoding="UTF-8"?> <module rename-to='paginaweb'> <inherits name='com.google.gwt.user.User'/> <inherits name="com.google.gwt.place.Place"/> <inherits name="com.google.gwt.activity.Activity"/> <entry-point class='com.paginaweb.client.PaginaWeb'/> <replace-with class="com.paginaweb.client.ClientFactoryImpl"> <when-type-is class="com.paginaweb.client.ClientFactory"/> </replace-with> <source path='client'/> <source path='shared'/> </module>
En el paquete client.ui crear la interfaz IndexView.java para la vista principal
package com.paginaweb.client.ui; import com.google.gwt.place.shared.Place; import com.google.gwt.user.client.ui.IsWidget; public interface IndexView extends IsWidget { void setName(String name); void setPresenter(Presenter listener); public interface Presenter { void goTo(Place place); } }
Click derecho en el paquete client.ui ir a New->UiBinder
El asistente creara los archivos UiBinder IndexViewImpl.ui.xml y su clase manejadora IndexViewImpl.java
Luego modifico la clase IndexViewImpl.java
package com.paginaweb.client.ui; import com.google.gwt.core.client.GWT; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Widget; public class IndexViewImpl extends Composite implements IndexView { private static Binder uiBinder = GWT .create(Binder.class); interface Binder extends UiBinder<Widget, IndexViewImpl> { } private Presenter listener; private String name; public IndexViewImpl() { initWidget(uiBinder.createAndBindUi(this)); } @Override public void setPresenter(Presenter listener) { this.listener = listener; } @Override public void setName(String name) { this.name = name; } }
El archivo uibinder solo mostrara un mensaje
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent"> <ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui"> <ui:style> </ui:style> <g:HTMLPanel> Hello Activities and Places </g:HTMLPanel> </ui:UiBinder>
Activities and Places
De acuerdo a la página de google un activity representa una acción del usuario. Un Activity no contiene Widgets ni código UiBinder. Se encarga de inicializar y cargar la correspondiente vista.
Un place representa un estado particular de la interfaz.
Activities son como controllers y un Place corresponde a una URL asociada a una vista.
En GWT solo se utiliza un archivo HTML para un modulo, las vistas se diferencian por un #token que se añade al final de la URL.
Crear la clase IndexPlace.java en el paquete client.place
agregando el código necesario luce así:
package com.paginaweb.client.place; import com.google.gwt.place.shared.Place; import com.google.gwt.place.shared.PlaceTokenizer; public class IndexPlace extends Place { private String name; public IndexPlace(String token){ this.name = token; } public String getName() { return name; } public static class Tokenizer implements PlaceTokenizer<IndexPlace>{ @Override public IndexPlace getPlace(String token) { return new IndexPlace(token); } @Override public String getToken(IndexPlace place) { return place.getName(); } } }
En la interfaz ClientFactory añado un metodo para devolver la vista IndexView
package com.paginaweb.client; import com.google.gwt.event.shared.EventBus; import com.google.gwt.place.shared.PlaceController; import com.paginaweb.client.ui.IndexView; public interface ClientFactory { EventBus getEventBus(); PlaceController getPlaceController(); IndexView getIndexView(); }
En la clase ClientFactoryImpl se implementa el metodo añadido:
package com.paginaweb.client; import com.google.gwt.event.shared.EventBus; import com.google.gwt.event.shared.SimpleEventBus; import com.google.gwt.place.shared.PlaceController; import com.paginaweb.client.ui.IndexView; import com.paginaweb.client.ui.IndexViewImpl; public class ClientFactoryImpl implements ClientFactory { private static final EventBus eventBus = new SimpleEventBus(); private static final PlaceController placeController = new PlaceController(eventBus); private static final IndexView indexview = new IndexViewImpl(); @Override public EventBus getEventBus() { return eventBus; } @Override public PlaceController getPlaceController() { return placeController; } @Override public IndexView getIndexView() { return indexview; } }
Creo la clase IndexActivity.java en el paquete client.activity
package com.paginaweb.client.activity; import com.google.gwt.activity.shared.AbstractActivity; import com.google.gwt.event.shared.EventBus; import com.google.gwt.place.shared.Place; import com.google.gwt.user.client.ui.AcceptsOneWidget; import com.paginaweb.client.ClientFactory; import com.paginaweb.client.place.IndexPlace; import com.paginaweb.client.ui.IndexView; public class IndexActivity extends AbstractActivity implements IndexView.Presenter { private ClientFactory clientFactory; private String name; public IndexActivity(IndexPlace place, ClientFactory clientFactory){ this.name = place.getName(); this.clientFactory = clientFactory; } @Override public void start(AcceptsOneWidget panel, EventBus eventBus) { IndexView view = clientFactory.getIndexView(); view.setName(name); view.setPresenter(this); panel.setWidget(view.asWidget()); } @Override public void goTo(Place place) { clientFactory.getPlaceController().goTo(place); } }
modifico la interfaz AppPlaceHistoryMapper.java para agregarle el IndexPlace
package com.paginaweb.client.mvp; import com.google.gwt.place.shared.PlaceHistoryMapper; import com.google.gwt.place.shared.WithTokenizers; import com.paginaweb.client.place.IndexPlace; @WithTokenizers({IndexPlace.Tokenizer.class}) public interface AppPlaceHistoryMapper extends PlaceHistoryMapper { }
luego agrego el código al metodo getActivity de la clase AppActivityMapper
package com.paginaweb.client.mvp; import com.google.gwt.activity.shared.Activity; import com.google.gwt.activity.shared.ActivityMapper; import com.google.gwt.place.shared.Place; import com.paginaweb.client.ClientFactory; import com.paginaweb.client.activity.IndexActivity; import com.paginaweb.client.place.IndexPlace; public class AppActivityMapper implements ActivityMapper { private ClientFactory clientFactory; public AppActivityMapper(ClientFactory clientFactory) { this.clientFactory = clientFactory; } @Override public Activity getActivity(Place place) { if(place instanceof IndexPlace) return new IndexActivity((IndexPlace)place, clientFactory); return null; } }
por último modifico mi clase entrypoint PaginaWeb
package com.paginaweb.client; import com.google.gwt.activity.shared.ActivityManager; import com.google.gwt.activity.shared.ActivityMapper; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.client.GWT; import com.google.gwt.event.shared.EventBus; import com.google.gwt.place.shared.Place; import com.google.gwt.place.shared.PlaceController; import com.google.gwt.place.shared.PlaceHistoryHandler; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.SimplePanel; import com.paginaweb.client.mvp.AppActivityMapper; import com.paginaweb.client.mvp.AppPlaceHistoryMapper; import com.paginaweb.client.place.IndexPlace; public class PaginaWeb implements EntryPoint { private Place defaultPlace = new IndexPlace("index"); private SimplePanel appWidget = new SimplePanel(); public void onModuleLoad() { ClientFactory clientFactory = GWT.create(ClientFactory.class); EventBus eventBus = clientFactory.getEventBus(); PlaceController placeController = clientFactory.getPlaceController(); ActivityMapper activityMapper = new AppActivityMapper(clientFactory); ActivityManager activityManager = new ActivityManager(activityMapper, eventBus); activityManager.setDisplay(appWidget); AppPlaceHistoryMapper historyMapper = GWT .create(AppPlaceHistoryMapper.class); PlaceHistoryHandler historyHandler = new PlaceHistoryHandler(historyMapper); historyHandler.register(placeController, eventBus, defaultPlace); RootPanel.get().add(appWidget); historyHandler.handleCurrentHistory(); } }
Ahora ejecuto click derecho en el proyecto Run As->Web Application
La página muestra el mensaje
Hello Activities and Places
No hay comentarios:
Publicar un comentario