Interpreting GWT Venues / Events and MVP?

I understand that places and activities are separate from MVP. P & A is for managing browser history, and MVP is an architectural template. But, obviously, they alternate and intersect in regions, and this question concerns how they can interact with each other in unity.

I just read GWT Places and Activites, and recommended the MVP structure and my head is spinning. I need someone to confirm that I have a basic idea.

A PlaceHistoryHandler has both a PlaceController and a PlaceHistoryMapper . When you enter a specific URL into the address bar of a browser, PlaceHistoryHandler uses its PlaceHistoryMapper to determine which Place it should go to PlaceController . PlaceController , in turn, runs the corresponding PlaceChangeEvent on the EventBus .

One or more ActivityManager listen on the bus for such PlaceChangeEvent s and map these Place to an Activity , which should be a Presenter component in MVP.

The returned concrete Activity (presenter) must have an intuitive representation of the model (usually UiBinder) that implements AcceptsOneWidget . This AcceptsOneWidget component AcceptsOneWidget then launched (via Activity#start(...) ), and GWT - automatically - presents its contents in the browser.

Am I saying something wrong, misleading or misunderstood? If yes, please correct me. Based on this understanding, a lot of code will be written ...

+4
source share
3 answers

Maybe this might help you a bit.

I used this scheme when I was confused:

enter image description here

+2
source

It sounds like you have a pretty decent understanding of the concepts. I have used the Activities / Places API several times, and I still find it confusing. Here is another overview of how you can think about components:

PlaceController is what you use to tell the ActivityManager where to go next, using goTo.

ActivityManager - controls the actions. Allows start, stop, show, ect.

ActivityMapper - Think of it as a factory. He knows what activity should be created on the basis of a certain place. Here I usually add my RPC service.

A place. Think of it as an “address” to a specific view in an application. PlaceTokenizer is usually listed here, but it is more convenient.

PlaceHistoryMapper is a class that will take a url token, and using the PlaceTokenizers you specify, create a Place from it.

Act. The activity code should be able to take the Place object and get your application in this place. If two Place objects are the same, they should show the same thing every time.

Here is a (probably not stellar) example of a test application that I wrote that uses Jobs. I have two parts of the application that use this: https://github.com/aglassman/jgoo/tree/master/JGoo/src/com/jgoo/client/appnav https://github.com/aglassman/jgoo/ tree / master / JGoo / src / com / jgoo / client / crud / nav

Events Places are created here: https://github.com/aglassman/jgoo/blob/master/JGoo/src/com/jgoo/client/CrudLauncher.java

Here is a test application in action, you can see different ways to use PlaceTokenizers to access different views. (Please note that the data warehouse sometimes takes a few seconds to initialize, so if you "Get All" it may take some time to load (there is no boot counter, but it works). If you click on the result text, it will lead you to view of the object.

http://jgoo-sample.appspot.com/

Hope this helps!

UPDATE: added an example of an action as it relates to MVP

In my example below, a PlaceTokenizer supplies an activity type, and if editing is requested, a UUID is provided to map to a specific contact. I use Activity as a high-level leader, pretty much just to provide the lower-level leader with the raw data in the information that he needs to execute. In the lower level view, in this case RequestEditWidget and ContactInfoWidget, I use UIBinder to create the view. Please note that currently I have no way to use canStop / onStop methods, but this will just be additional code for interacting with my widgets.

Each of these (edit, subscribe, request_edit) could have everything in its activity, but I wanted all of them to have the same place prefix.

 package contactmanager.client.nav; import contactmanager.client.ContactManagerServiceAsync; import contactmanager.client.callback.BasicCallback; import contactmanager.client.contact.info.ContactInfoWidget; import contactmanager.client.contact.info.RequestEditWidget; import contactmanager.shared.bundle.InitDataBundle; import com.google.gwt.activity.shared.AbstractActivity; import com.google.gwt.event.shared.EventBus; import com.google.gwt.place.shared.PlaceController; import com.google.gwt.user.client.ui.AcceptsOneWidget; public class ContactActivity extends AbstractActivity{ public enum Activity { request_edit, edit, subscribe } private ContactManagerServiceAsync cmsa; private ContactPlace place; private PlaceController pc; public ContactActivity(PlaceController pc, ContactManagerServiceAsync cmsa,ContactPlace place) { this.pc = pc; this.cmsa = cmsa; this.place = place; } public void start(AcceptsOneWidget panel, EventBus eventBus) { switch(place.activity) { case request_edit: loadRequestEditPanel(panel); break; case edit: loadEditPanel(panel); break; case subscribe: loadSubscribePanel(panel); break; } } private void loadSubscribePanel(final AcceptsOneWidget panel) { cmsa.getInitDataBundle(new BasicCallback<InitDataBundle>() { @Override public void onSuccess(InitDataBundle result) { panel.setWidget(new ContactInfoWidget(pc,cmsa,result,null).getWidget()); } }); } private void loadRequestEditPanel(final AcceptsOneWidget panel) { panel.setWidget(new RequestEditWidget(pc,cmsa).getWidget()); } private void loadEditPanel(final AcceptsOneWidget panel) { cmsa.getInitDataBundle(new BasicCallback<InitDataBundle>() { public void onSuccess(InitDataBundle result) { panel.setWidget(new ContactInfoWidget(pc,cmsa,result,place.uuid).getWidget()); } }); } } 
+2
source

You have one thing: you initialize the ActivityManager using AcceptsOneWidget and ActivityMapper (and the global EventBus ). ActivityManager listens for PlaceChangeEvent and requests an ActivityMapper for the corresponding Activity , and by start() it, passing AcceptsOneWidget , it was initialized with and a ResetableEventBus , which wraps the global EventBus .
AcceptsOneWidget is the slot on the page that will receive the view for activity. When an action begins, it then passes on its view (as IsWidget ; hint: Widget implements IsWidget ) to AcceptsOneWidget , as well as how it signals “this is what to display and show it now.” ”Note that it can do this synchronously ( from inside start() ) or asynchronously (for example, from a response to an RPC called by start() ).

Regarding MVP, many use Activity as a host, but this is just one way to do MVP:

  • some actions are used only as life cycle controls for other components (for example, widgets) that themselves use MVP (or not). Thus, the activity could create a presenter and presentation (or choose long-lived instances of any of them; again, as a rule, the host is short-lived, while the -heavier to build view is long-lived, for example, singleton) and initializes / reset them to the correct one state; or it can just create / reuse the widget and initialize / reset it.
  • some use MVP inside widgets as an implementation detail. CellTable (and in fact almost all cell-based widgets) is one such example: it is sophisticated enough for the presenter to have real value, but this presenter is not exposed at all in the API. You can mix this approach with the above: the action creates / reuses the widget and initializes / resets it, and the widget uses MVP inside.

If you want to know more about places and events, I would advise you to read my blog posts about them:

This, of course, is in addition to the official documentation .

+2
source

Source: https://habr.com/ru/post/1488125/


All Articles