I'm currently working on a GWT application and I'm still a little fuzzy on how it all fits together (the joy of having to make changes without first coming to an understanding of the whole framework, although that might be difficult anyway).
We have a few Activities that all correspond to parts of the UI (e.g. main content, a toolbar and a list of things). I'm not really sure whether that's even how Activities are intended but I guess I can't really change that easily now. My problem now is that the list of things holds state (the current selection) that the main content also needs and in a way the toolbar too (at least the toolbar currently has it – I'm beyond asking).
But what would actually be an appropriate place to store that? I guess coupling the actual view implementations together and storing the selection only in the list isn't such a bright idea.
I see two main solutions here:
keep the state within each activity and keep them synchronized through events (on the EventBus). That is: the "list of things" has a current selection, main view has one too, so does the toolbar; and each time that value changes, the activity that's making the change fires an event on the event bus so that the other activities can update their state, so that all activities have the same value in their own state.
use a singleton object (if you're using GIN and dependency injection, simply annotate the object with #Singleton and inject it in all the activities) to keep the state at a central place. The activities register event handlers on the state holder object to be notified when it changes. That is, each time an activity calls setCurrentSelection (for example), an event is fired (for example a ValueChangeEvent), and because all activities listen for it, they can update their view or whatever depending on the new value. You can choose to either dispatch the event on the event bus (similar to the PlaceController) or have the state holder implement HasValueChangeHandlers. Just make sure to unregister the handlers when the activities stop to avoid memory leaks (dispatching on the event bus makes it easier: simply register the handlers on the bus passed as argument to the start method and they'll be unregistered automatically when the activity stops, and you don't even have to think about it).
Actually, PlaceController is a good example of such shared state (the current place).
Related
I'm new to GWT. I creating a MVP based project (as described here) that uses a number of custom events. There are several widgets (10+) that listen for some global events and perform some action (including writing to the DOM) in the event handlers.
What I'm finding is that the UI blocks and doesn't update until each and every one of the handlers for the one event finishes processing. This is causing the UI to perform slowly on page load and for any other events that cause the widget to update.
I created a similar project in plain JavaScript/jQuery and this was not an issue with that project. In fact, the UI was blazing fast. What am I doing wrong here? The documentation states that GWT is very performant, so I have to conclude that I'm just doing it wrong.
One example, I have a drop down that selects a date preset (like Yesterday, or Last Week). When this happens I set the selected preset in the model like so:
public void setDateRange(DatePreset dateRange) {
this.dateRange = dateRange;
eventBus.fireEvent(new DateChangedEvent(dateRange));
}
Each of the widgets has access to the same eventbus and registers to handler DateChanged events. Each of the widgets needs to do a fair amount of logic and processing (including making an ajax call) to then update itself with correct data.
#Override
public void onDateChanged(DateChangedEvent event) {
DatePreset dateRange = event.getDate();
… additional processing and logic
… ajax call
}
I've determined after some basic profiling that each widget requires about 100-150ms to finish processing (which means there's a UI delay of over one to two seconds). When I say blocking, I mean the dropdown where I selected the date preset doesn't even close (and I see the spinny wheel) until everything finishes.
What can I do to make this run faster (and without UI blocking)? I am open to any ideas. Thanks!
Measuring the speed of the project in developer mode can be a reason for this extreme slowness.
You can check out the real speed of the application if you deploy it to an appserver or if you delete the &gwt.codesvr=127.0.0.1:9997 part from the end of the url in devmode.
Where exactly is the limit to adopt VM so it can suite better a particular View? Example:
There should be a command in UI (ex button) that should allow adding new item. Additional requirement can be that new item should be selected, ensured that its visible on control (lets say TreeView control), and to begin edit on the newly added item (in order to change predefined value that was set in VM). Lets assume that control doesn't have automatic mechanism to achieve this, so we need to do it manually. So the execution flow looks like this:
invoke add command on VM - done is View's xaml.
set SelectedItem to new item (usually we bind control's SelectedItem property to VM's CurrentItem property, and then just assign new item to CurrentItem.
ensure that new item is visible on control - this must be done in View's code behind.
Start editing - this must be done in View's code behind.
Now, since everywhere on net there are articles on using messages for almost everything, a question:
What do I break if I do it in the simple old fashion way? I use Click event instead of Command binding on adding new item, and in the method I do this:
// in View's Click event handler
ViewModel.AddCommand.Execute(null);
EnsureVisibleSelectedItem();
BeginEdit();
.. clean and clear! And what do I gain if I do it using messages:
// in ViewModel's AddCommand
AddNewItem();
SetCurrentItem();
SendMessageToEnsureVisibleSelectedItem();
SendMessageToBeginEditSelectedItem();
... where View has registered to receive these two messages.
Any light on this is greatly appreciated. To my opinion, UI can change, and VM should be able to adopt new UI without making changes to itself, so I dont quite understand current MVVM policy that is preached on internet.
I would say "make it simple".
What's really important in MVVM is:
what doesn't depend on the view should go in the ViewModel (your ViewModel must not be aware of the view in any way - not just by object reference)
everything else in the View and its code-behind.
Yes, in its code-behind. There's nothing wrong in writing code-behind if it is code that is related to the view, not logic. For instance, drag & drop management should be written in the code-behind.
To answer your question, you do not break anything in writing:
// in View's Click event handler
ViewModel.AddCommand.Execute(null);
EnsureVisibleSelectedItem();
BeginEdit();
Everything that is not related to the view is in the ViewModel, everything else in the View/code-behind. That's just fine.
No if I look at your second example:
// in ViewModel's AddCommand
AddNewItem();
SetCurrentItem();
SendMessageToEnsureVisibleSelectedItem();
SendMessageToBeginEditSelectedItem();
AddNewItem is OK (not related to the view), SetCurrentItem is OK (not related to the view), but what about SendMessageToEnsureVisibleSelectedItem and SendMessageToBeginEditSelectedItem?
EnsureVisible is typically useful for a treeview, but what if your view wasn't built with a treeview? What if the control would automatically make the new selected item visible? Of course you could ignore the message, but you would have written some useless code in ViewModel because you thought your view would need it for UI display.
You have typically written here some code in the ViewModel that is aware of how the View should be working. Yes, you have reduced the number of lines in the code-behind, but you definitely have broken the pattern.
Your "old fashion way" is actually a good way for your needs. Your ViewModel is not aware of the view, that's what's important.
Consider these two scenarios:
a user presses a button in a view (e.g. Fulfill Order) and we want the view to update immediately (disable the button, add a progress bar, etc.)
a service layer raises a business event, which ultimately must be reflected on the view (e.g. a product has become out-of-stock).
Both cases legitimately require some mechanism, X, to update the viewmodel. With MVVM, the view can do this by setting properties of the viewmodel in an event handler, through command binding, or via some other mechanism.
The service layer can do this using some mechanism, Y. For example, raising events in the business/domain model, creating commands to manipulate the viewmodel, calling methods on the viewmodel etc.
In fact, X and Y could be the same mechanism (or pattern).
What's a good one to do this, that keeps to the spirit of MVVM, but is DRY?
I think you need to pick an MVVM framework and follow the pattern for this that it supports.
In general:
Your button will be hooked to a FulfillOrder method on your ViewModel, via an ICommand or whichever your MVVM-framework supports
A "CanFulfillOrder" boolean property will be hooked up to disable your button via INotifyPropertyChanged, this can be triggered by the FulfillOrder method or the event you mention. It could also be bound to the Visibility on a progress bar.
Another property could provide the percentage on the progress bar and update it appropriately
A good, general-purpose MVVM framework is MVVM Light.
If you are looking for more power, and can handle more complexity, try Caliburn.
Or if you want to use dynamic and try something cutting edge, try my framework: NoMvvm.
I am making an application where I have three main Presenters.
In one say "ListPresenter", I have a Tree with a list of cities.
In one say "WritePresenter", I type in some text and hit update. The update is for one of the cities.
In one say "ShowPresenter", I show the update if and only if an update is availaible for that city which is currently clicked in our list.
Now the way I am doing it is...
WritePresenter fires an event on the EventBus with details of for which item the event is being fired. ShowPresenter listens to these events and based on the ListPresenter state needs to update itself.
Now how should ShowPresenter get access to ListPresenter state. I could just get a refrence of it from the Class which instantiate ListPresenter. But that dosent seem to be a good design idea. Also seems to be increasing coupling.
What can be the best possible way around?
How about making ListPresenter fire another event that ShowPresenter would be subscribed to. That event would be fired if, and only if, ListPresenter is in such a state that ShowPresenter should be updated.
first post don't hurt me :)
I am using a BorderLayout with the usual North, West, Center, South Panels. On the West ContentPanel, I've got a Tree. If an event (OnClick)occurs I want a particular dialog box displayed on the Center ContentPanel.
What is the best way for me to do this? Currently I'm using a function called returnPanel() that returns the center ContentPanel. In the event handler I call this function (MainWindow.returnPanel().add(myDialog)).
The way you are doing it is intuitive and works, but will start causing hell when the application grows, because different parts of the application are strongly coupled. The solutions to this problems are the MVC design pattern and the observer design pattern.
Ideally, using the MVC pattern, you don't want any widget to 'know' of any other widget. There is only class that knows all the widgets, which is the Controller. Anytime one widget needs to message/signal another widget, it tells it to the Controller class, which relays the message in the appropriate way to the appropriate widget. In this way, the two widgets are decpoupled and one can change without breaking the other. You may want to use an enum to enumerate all possible actions to which the controller has to responsd.
If your widget has to call only the Controller when an event occurs, you may simply call an aptly named (static) method on it and be done with it. However, as soon as multiple other classes needs to be informed of an event, you are better of using the Observer pattern, which allows you to signal multiple other classes, without changing your class. It simply calls notifyPObservers() in the eventHandler and that's it. How many listeners there are, and what type they are, is irrelevant. This way, you also decouple a class from it's listeners. Even if only the Controller listens, it may be advisable to use the pattern, as it clearly seperated the 'call back' code from the other code in the classes.
BTW, this has nothing to do with GWT or even Java in particular.