I need help. I am struggling to get my Observers working in java. Can someone explain to me using MODEL-VIEW-CONTROLLER Architecture how to create and observer from View To Controller.
This is because if i press a button on the view the action event has to call notify the controller of that button being pressed.
For that I'm implementing observers to minimize class coupling.
I have a class Controller, View (Swing using JFrame), and an Application Class that holds the main method.
I tried implementing it so that Controller implements Observer and the View extends Observable.
After triggering the event of clicking the button all code except the notifyObservers("OBJECT") gets called. It disappears somewhere in the java library.
Any Help Will be much appreciated.
the model should extend observable and the view should implement observer (you want the view to depend on the model). you will need to call setChanged to after you change the state of the model to force the observers to be notified.
Double check, that your controller is really observing/listening to the (correct) button instance. Use a debugger and set some breakpoints to check whether notifyObservers is called and who is receiving the notification.
Related
I trying to refactor one of my activity class to implement mvp(using mvp mosby library) . I have a RecyclerView and in this view there is some items that some changes apply to them during the run time. for example I do some I/O operation and change one row.
I think it's better to keep my items in presenter class; what is the best practice for this? keep this in 1)presenter or 2)activity or 3)only keep view related item in adapter and all other item in presenter.
the activity now keep items directly and change item row in activity and then notify adapter. isn't better to move all this line in adapter and notify adapter in the adapter class? for example i want change icon of some row.where and which class is responsible for that? adapter? activity? now I want to implement it like this in adapter:
changeItemIcon(int position, int iconRes){
mImages.get(position).setICon(iconRes);
notifyItemChanged(position);
}
I invoke this method on activity and invoke activity method from presenter.
is it good? what is the best practice to do this?
UPDATE
also I find this question ( Best way to update data with a RecyclerView adapter ) that using adapter method for changing items. but what about modify? Need I keep reference to items in my activity?
for example i want change icon of some row.where and which class is responsible for that? adapter? activity?
I know it sounds a little bit strange, but changing an element is always the responsibility of your "business logic", even just for "icons".
The workflow should be as follows (unidirectional data flow):
View appeares, tells presenter to load a list of items
Presenter loads items form "business logic" and registers himself as an
observer / listener / callback (whatever you want to call it)
Presenter receives result and tells the view to display the list of
items (through RecyclerView and corresponding adapter).
so far is what you have implemented I guess, now it comes to the point where you want to change an item.
User clicks on an item in your RecyclerView which then should trigger to change the icon of this item. Therefore View should call: presenter.changeItem()
Presenter is just the man in the middle in this case and will invoke the "business logic layer" to tell that the item should be changed to new state (icon has changed).
"Business logic layer" will change the models state (change the items icon) and then will notify its observer / listeners that the model has been changed.
Since Presenter is still observing / listening to the business logic layer (see point 2.) the Presenter will be notified (see point 6.) with a new (updated) list of items containing the updated item which icon has been changed.
Similar to point 3. Presenter will tell the view to display the new (updated) list of items (through RecyclerView and corresponding adapter).
Do you see the unidirectional data flow? That is very important. Immutability FTW.
MVP has two different variants: Passive View and Supervising Controller. Depending on your taste, you can stick to one or mix both of them in your app.
If you choose Passive View, you need to hide Model from View and let Presenter format data then set to the View. In this case, you need to keep Model reference in Presenter. View should only hold view-data (adapter) for its displaying purpose.
If you stick to Supervising Controller, you can allow View to directly bind data from Model and ask Model to perform some simple logic. Presenter should only care complex logic, i.e some operations which need to involve Services. In this case, you can give Model (your items) to View (activity) and let it interact with Model in some simple manner.
PS: Please also check out our new MVP framework: Robo MVP at http://robo-creative.github.io/mvp.
I've never used mosby, but I've just read their docs (good reading btw) and here's my understanding:
A recycler view usually consists of the view (android term) and an adapter. Both are connected inside a fragment or activity. In terms of MVP/mosby this is all view layer. The presenter should only retrieve and pass the to-be-shown data from your service (model layer in mosby, "service layer" or "business logic" in other concepts), which in turn gets it from a DAO or repository (model layer).
The docs say that the presenter only handles the view state, not the actual contents. Your state is "showing list".
Before some time, i started looking for a pattern to decouple UI from a logic of my app. I decided to use MVP, but there is one significant problem which i cant solve.
How can i inject a instance of presenter into view, if classes that implements Application, are launched from static method. There is also no choice to launch specific instance of class implementing Application, so parameters in constructor are useless.
Also i do not use FXML, my view class is coded in java.
PS: Sorry for my english, as it's not my native language
You can pass a reference from say Main.java to a Presenter. In Main do this:
Presenter p = new Presenter(); // This is your Presenter class
p.setReference(this); // Call a method in the presenter
// and here is a method in Main.java just as an example
public StackPane getRootView(){
return this.rootView;
}
Then in Presenter you have:
private Main main;
public void setReference (Main main) {
this.main = main;
}
Your presenter can now call methods in Main e.g.
StackPane sp = main.getRootView();
You could also do this in the constructor of Presenter.
I have written a sample code to answer to this problematic.
https://github.com/oterrien/JavaFX_Presenter.git
The view interface provides the intention of the view.
For example:
getting and setting text
getting and setting result1
getting and setting result2
getting and setting event handler for the Add button
The concret view is created from FXML file. Each field of the control is defined with #FXML. The action to be triggered when the button is clicked is also a method and is prefixed by #FXML.
The concret view implements the interface by providing a mapping between #FXML fields and getting/setting methods. And the triggered method does just call the event handler.
The concret view is also responsible of creating the presenter (which refers itself as view).
That is the important point. The presenter acts upon the model and the view. It retrieves data from repositories (the model), and formats it for display in the view.
For that purpose, the presenter should be able to call the view in order to set data and retrieve data once updated by user. That is why, the presenter contains a reference of the view. But it should also provide action to be done when view's event handlers are called.
When a user clicks on button "Add", the method which is bound with FXML is called. This method call the EventHandler which has been set by the presenter. In other words, the presenter is responsible of registering its own method to the view's EventHandler.
Finally, testing the presenter just consists in creating a mock of the view.
I built a Event Notification system that receives events generated by devices. I had 2 main components: Listener and Publisher. Publisher will send polling command to device and catches the events. Then, it will notify all events to Listener via EventBus (I used EventBus library of Guava). Now I implement a View component. View is Observer and Model is Observable. When listener receives an event, it will notify to Views.
View extends JFrame and implements Observer. In the constructor like:
public View(Listener), I just register View as an Observer to Listener
The problem is when I close the view, the program is closed too. How can I make the view independent on Model?
Please help me.
I think you could create a control package, which would be responsible for sending messages from the view to the model.
I am unable to understand the meaning of Has****Handlers interfaces in GWT. What would be the difference if a class implements HasClickHandlers (addClickHandler) and ClickHandler (onClick) interfaces.
thank you
HasClickHandlers - something that can be clicked, e.g. a button
ClickHandler - some code that handles on a click
A HasClickHandlers object is a widget, like a button, that can react when the user clicks on it. But a button by itself does not know what should happen when a user clicks on it. A developer can craft a ClickHandler object, which is some code that implements what should happen when the user clicks on that button. A button can be given a ClickHandler to react to the user's click, i.e. the button can have/hold a click handler - HasClickHandlers.
One may ask why does GWT say applications should define view interfaces with method signatures like:
HasClickHandlers getSaveButton();
instead of simply
Button getSaveButton();
Google advocates decoupling the view from presenter. The presenter usually cares very little for all the functionality of a button - it usually only cares that the button is something that can take a click handler and use it. An interface like HasClickHandler has very few methods and is very easy to mock. Using a real button however will sometimes require initializing some or part of the whole UI framework and instantiating prerequisite context classes in order to create a button for testing.
By having the interface return HasClickHandler instead Button, the unit test code for the presenter can decouple completely from the complexity of the UI framework by simply mocking interfaces like HasClickHandler. This means simpler test scaffolding and very fast unit tests (since you don't have the overhead of initializing/interacting with a UI framework).
http://googletesting.blogspot.com/2009/08/tott-testing-gwt-without-gwttest.html
Edit
OP asks:
ok, e.g. if ABC class implements Hasclickhandlers and Clickhandler and then onClick and addClickHandler (which returns HandlerRegistration), it means that 1)it will act on click event thru onClick method and 2)will let any other class(es) know (who is implementing ClickHandler and used addClickHandler of ABC class to register the event) that click has just been occurred? right?
Your classes like ABC will not implement HasClickHandlers. Only GWT widgets like buttons implement HasClickHandlers. Google is simply providing the HasClickHandlers interface as an alternative way to declare variable references to some widgets like buttons. These widgets will notify registered ClickHandler about a button click.
Your class ABC may implement ClickHandler or may contain an inner (possible anonymous) class that derives from ClickHandler. A typical usage looks like:
public class ABC {
...
getSaveButton().addClickHandler(
new ClickHandler() {
public void onClick(ClickEvent event) {
saveToDatabase();
}
}
}
...
The HasClickHandlers is for objects that generate click events. The ClickHandler is for objects that deal with the events.
For example, a Button will generate a click event. When you want to handle a click event, you create a ClickHandler that contains the code that does so. You register this ClickHandler with the Button object so that when a click happens, the Button knows who to tell about it. The HasClickHandlers interface is implemented by Button (via the FocusWidget parent class) which is just the interface for registering ClickHandlers. This interface simply standardizes the registering of ClickHandlers.
First time posting a question on StackOverflow, so please go easy on me :)
From what I understand, proper use of the model-view-controller pattern requires that we decouple the view and controller such that the view knows nothing about the controller. I'm having a bit of a problem understanding how to do this using Java Swing.
Say I have a view (some class that would extend JFrame), and this view has a button. Is it safe to say that I would want to register the controller as an ActionListener of the button? Or do I make it a listener of the entire view itself.
And how do I go about doing this without doing something like:
button.addActionListener(myController)
in the view, because if I were to do this in the view code, wouldn't it now have a dependency on the controller?
I didn't post any code because, frankly I don't have much to go on at the moment.
any help is appreicated!
It might help to not think of the view in terms of buttons etc. so much as an interface. The interface makes it possible for web ui's, command line consoles, etc. to be written and fulfill the role of the view.
In the case of your button event, the button represents a call to some command carried out by the controller.
So, you could have an interface like this:
public interface MyViewIf {
// used by the controller to register its self as a listener of the view
public addViewListener(ViewListener vl);
...
}
and:
public interface ViewListenerIf {
// used by the View to notify any listeners of control events etc.
public onViewEvent(ViewEvent ve);
}
Then your controller would implement ViewListenerIf and register it's self with a factory generated instance of MyViewIf. That way the controller doesnt need to know any specifics about your view class(es).
Your view class would then internally handle it's own button events, turn them into ViewEvent objects and call onViewEvent() on the controller that registered it's self with the view, leaving the View 100% oblivious to the existence of the Controller.
Make an actionlistener in your view class. From your actionlistener you call your controller.
Code for actionlistener:
controller.doButtonClick();
This means you need to inject your model and controller to the view. That is how I do it.
Take a look at the Spring Framework to get an insight in implementing the MVC pattern.
Brief Spring tutorial Tutorial