I am looking at this GWT MVP tutorial:
http://www.gwtproject.org/articles/mvp-architecture.html#binding
The data is passed from the presenter to the view using this method:
display.setData(data);
where data is ArrayList<String>
How would I pass the data between view and presenter if I had something like a SelectBox in my view where I can select multiple values that I probably populate from a database?
I would store the SelectBox values probably in a HashMap.
Should I implement a second method to pass this to the presenter or should I try to keep the communication between view and presenter down to just one method?
In essence: How can views and presenters communicate through a simple method that ideally takes only one parameter, taking into consideration that sometimes I need to pass a simple string which represents an e-mail address and sometimes something more complex such as the values of a SelectBox?
You can add as many methods as you like to make your communication between your VIEWS & PRESENTERS! The key point lies in the choice of your methods and the implementation, because, debugging a GWT code-base is a nightmare!
There are approaches that you could choose from:
You can have a DISPLAY interface of your PRESENTER be implemented on your VIEW
You could generate an event (on MULTI-SELECT of Values from your SelectBox on VIEW), implement a corresponding handler on your PRESENTER to overcome multiple methods that need to be put in your DISPLAY interface!
Choose your option, based on your requirement and also on the complexity of it! My suggestion is to have an event, since the same piece of code can be reused somewhere else as well!
Related
I have tried to adhere to the mvc pattern in the java code that I have written. I want to keep the view and model independant of the controller and from each other. I am also trying my best to use interfaces to keep things modular.
My view has JButtons that I want to "bind" to specific methods in the model through the controller. I have tried two approaches to still keep the view independent of controller:
Registered the controller as an ActionListener to the view-object. Pros: The void addListener(ActionListener listener) abstract method encapsulates this behaviour in the view interface, so more buttons can be added without changing the interface. It also decouples the controller from the view, since it does not know anything about the actual buttons in the view. It is also easier to add more views or more controllers, so it follows the open-closed principle well. Con: For the controller to know the nature of the ActionEvent, I have only been able to come up with using the ActionEvent.getActionCommaned() in a switch statement, so mapping each case to its' corresponding method in the model. This seem unsafe and prone to cause irritation, since it seems like bad practice to match strings like this.
I also came up with adding public addActionListener(ActionListener) methods for each button in the view, like addGasButtonListener(ActionListener). Then doing something like view.addGasListener(e -> model.gasVehicles(view.getGasAmount())) in the controller. Pro: This seems like it reduces the uncertainty of matching strings. Cons: It means I have to add these new methods to the view interface, and each time a new button is added I have to do the same, making it difficult to add new views that does not have anything to do with some of the methods.
Main question:
I prefer the first method since it seems better to me, but I still would like to find a way to avoid matching strings, and find some nice way to do it (more similar to the rigidity of the second way of binding buttons to methdods). Is there?
Follow-up (less important) question:
I should also mention that my controller contains an inner class TimerListener implements ActionListener, that contains the loop of the app that acts on ActionEvents from the Timer. It also acts on ActionEvents from buttons if approach number one is used, which is why my follow-up question is: how would I seperate this main loop that only cares about the timer, from the switch statement used to act on button events. Since the ActionEvent.getActionCommand() is null almost all the time, it would be nice to seperate the two. Is there a approach that would let me do that?
I don't really see the value of working with ActionListener instances in the first place.
From your own example:
view.addGasListener(e -> model.gasVehicles(view.getGasAmount()))
You don't do anything with the actual event
In case you decide to use a different UI element in the future that doesn't fire ActionEvents, you will have to change the type of the listener.
I would rather expose a custom listener/callback that the controller (or model) can register on the view:
void onGasAmountChange(double gasAmount);
That being said, you might be focusing too hard on having a model, view and controller. If you look at more complicated Swing components (JList, JTable, ...), they have a view component and a model (ListModel and TableModel).
You could do something similar and create your own model for your view, and let the view call the necessary methods on the model directly (just like it happens for those Swing components).
That avoids having to write a bunch of one-liner listeners that basically delegate to the model.
I can see several ways of doing this.
Have a reference to a single controller in the model. Model sends event to this controller and other controllers get to know it through the hierarchy and passes on to views
Have all interested controllers be listeners on the model (the model has a list of listeners ). The view gets to know the change through the controller
Have all interested views be listeners on the model. ( The view gets to know the change directly)
Which is appropriate and why?
your third Option is old school. The views get notified by the model, and the view decides how to handle this. It's okay but other options are better.
your second option sounds good. The views get notified by the controller(make sure you have different controller for updating the views and updating the model). So the controller can modifiy the events before passing them to the view. The controller can hier customise the Data for the views. the View shouldn't do this, there job is only to show something(in option three the views have to do this).
your first option is a small improvment of option two with a hierarchy. It's may be better in a complex scenario, to filter the event passing. But normaly this will blow up the overhead. So it is harder to read.
I would choose option two. It's the best trade of simple code and the option for complex actions.
What is the best way to support two views over the same data, with both views allowing edits on the data, in presence of various listeners in the UI and the underlying model.
Example, simple approach is to bind JTable with an AbstractTableModel instance, and pass reference of AbstractTableModel instance to the other view as well.
But if the other view chooses to change the underlying abstract table model instance, and in presence of some other listeners, like table model listener and some listeners on the JTable, it gets complicated very quickly, at least for me.
Not entirely sure, but it should be possible for some combination of these objects to lead to events being raised inadvertently.
I am not aware of any patterns in swing that can help with this problem, but apparently MVC is not encouraged in Swing.
In the past, I would have chosen to ensure that only the model raises events, and that changes the view, called the passive view pattern.
Your thoughts? (Swing and application design newbie here.)
I would recommend to centralize your data in some sort of cache object in something like a list, because imagine you get more then just two views to display the same data, it can get kinda messy to carry your tablemodel all around.
So simply let your cachelist inform about your data changes (update, create, delete...) by an own implementation of propertychangelistener or just with an eventbus. All interested views can sign up at your cache for data changes and get informed automatically. So neither of the views need to know each other which keeps your code kinda simple and easy to maintain and expandable for other views.
You can totally deviate from the listening scheme and switch to an EventBus based scheme, I don't think it is hard to replicate in a Swing framework. It's a concept from the GWT framework. Your application should initialize an event bus and its reference must be passed to those "objects" which need to broadcast events. It should be a "singleton" class that passes around the same instance of the EventBus.
So the data modifiers in your model can "post" an event into the eventbus and any UI can wish to receive the broadcast. So a change in the model by one of your tables will broadcast an "update" event which is received by your other table, which inturn updates its display.
Design your callbacks well from the idea and you should be having a very simple and clean solution.
I've spent some hours reading various questions and answers regarding implementing the various MVC-type patterns in Android. I've seen a few code examples posted in various blogs. I would, however, still appreciate some ideas and opinions on what I am trying to achieve. Specifically, I'd like to work out the best code mechanism to inform a single View, or a group of Views, that a particular item of data has been changed.
My application is quite simply one which obtains measurement data from a hardware device via Bluetooth, and displays and logs that data. At present, I have a Service which takes care of Bluetooth communications and background logging. I have a 'global' data store class that is an extension of Application.
As measurement data is polled from the external device, the measurement data (which is in reality about thirty bytes of data) is updated in the data store object (which, in MVC terms, I'm guessing is the 'model').
At any time, only a small subset of that data will be displayed by UI Views. Typically, a given View will only be interested in representing one particular byte of measurement data. As the user moves to different Activity classes, other Views will be displayed which would display a different subset of that data.
So to get to the point, I'm trying to choose the best way to cause invalidate() to be invoked on interested Views when a given data item is changed.
The options seem to be:
Make use of the existing Observer class, and related classes.
Kind of 'roll my own' observer pattern, by creating my own register() and unregister() functions in the data model. Observer Views would be held in an ArrayList (or perhaps a more complex arrangement of one observer List per data item). I'd loop through this ArrayList each time data are updated and call invalidate() (or postInvalidate() of course, depending on my threading arrangement).
Are there any reasons why I should use one of the above over the other? And is there any other 'observer' mechanism I should consider?
Many views in Android are backed by some subclass of BaseAdapter which has a method notifyDataSetChanged() which instructs the view to refresh itself. If you are using a view (such as ListView or GridView or any descendent of AdapterView) then it is backed by a BaseAdapter and you can simply update that Adapter and the view will refresh itself.
I guess this means, I vote that you use the built-in observer pattern. If you are using a custom view then obviously this won't work and you would have to use a custom method of refreshing anyway.
Another Option would be to use the Android Intent framework. When new data is received in the service set the data to the universal model and broadcast an intent that the data has been updated using the Context.broadcastIntent(Intent) method. Any view that is interested in that data would register and unregister receivers using the Context.RegisterReceiver(Receiver) and Context.unregisterReceiver(Receiver) methods. From there the view would retrieve the data from the universal model and update the view accordingly.
I think this might be what the observer pattern in Android.Lifecycle.Observer package is doing behind the scenes.
I would like to start a discussion on separating pure model and UI model in Spring 3.
By pure model I mean main object/objects that I retrieve from database, let's say some "user account". It contains enough info to display it in HTML view or to pass it to web service.
By UI model I mean all the auxillary stuff I need in UI to work with that object. E.g. if a "user account" has "state", then I need to fetch all the "states" from the database for, say, a combo box. The views are tricky and in some cases they require more information, in others - less. It would also be nice to be able to alter some lists by adding items like "Select all", which is pure UI stuff (and not quite conveniently done from view template).
I heard there's so called Model-View-ViewModel pattern, which seems to address these issues, but I have never tried its implementations.
The solution I use right now is to break logics into two services - one for pure model and one for UI model. It looks like this:
#RequestMapping(value="app/user_accounts/{id}")
public String getUserAccount(#PathVariable("id") String id) {
service.getUserAccount(id); // Gets main object and puts it into model
presenter.formUserAccount(); // Gets all classifier for main object's properties
return "user_account";
}
What I dislike about this is that the view and its so-called view model are not attached to each other. I can call presenter.formUserAccount() and return totally unrelated view name.
Another approach I see is similar to Spring controller annotation. We have classes annotated as #ViewModels and methods which map to view names. An interceptor finds and executes these methods before rendering a certain view. These seems elegant enough, but requires much code writing.
How would you solve this problem?
I have been thinking about this in the context of Grails, which is based on Spring MVC. My approach is to use Command Objects as View Models as it gives you the data binding and validation features that you would want in a View Model. With Command Objects you can abstract your "Pure Model" (or Domain Model) out of your View by using the Command Objects to map the view properties onto you domain objects.