View is dependent on Model (MVC) - java

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.

Related

Android MVP best way to handle views with API call

I am having a question regarding how do I update my view or perform a fragment transition when the view goes to background and the API response comes as a callback.
For example I have a loginfragment. User clicks login button and the presenter takes it and gives it Interactor where I have my Rx observer who talks to repository and model and so on. The response comes back in maybe 3 to 5 seconds. Within this time, I press home button and my app goes to background. The presenter receives the response from Interactor callback and now wants to update the view but view is in background.
On login success, I want to make a fragment transition and go to Fragment B. But my view is in background. So when I bring my app back to foreground, I still see login screen although I already got a login success API response.
How do I handle view updates or fragment transition when view goes to background and what is the best way of doing it?
One approach is Model-View-Intent architecture in Mosby, in which the presenter stores the latest state of the view, and the view subscribes to the ViewState Observable in order to update. In such approach the view can subscribe in onStart(), when it is safe to make fragment transactions.
Another possible approach is that each view has a state (ViewState), that holds a queue of commands to the view. If the view is ready (onStart() was already called), then the command is passed to it immediately, otherwise it is saved to a queue and postponed until the view is ready. See how it is realized in Moxy.

In MVP structure which class responsible for keep list items and how to notify data change in this

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".

How to listen to any keyboard on the whole application?

We are trying to build android activity that listen to any key press (either character or command) something like custom EditText.
Is there something like keyboard hook in Windows OS available on Android?
Is it possible to listen for all key pressed for all controls (EditText and other controls)?
Could this be achieved by an activity that runs in the background?
EDIT
As for security, we want to get keyboard events only for our app activity, ex: when our activity is shown and focused.
The Activity's onKeyDown / up / etc method will get called if no View consumes the event.
When Views do consume the events, you will need either:
a custom version of each relevant class that forwards the key presses up to the activity.
add a text change listener or key listener to all TextViews in the view hierarchy (could use a recursive method to step through the entire hierarchy)
You can't listen for EditText keys from background process, as it is bounded to Keyboard activity that manipulate that text. It will be security valuation as it will not only allow you to listen to keys in your own application but for all others, including sensitive data like user passwords.
Handling Keyboard Actions
http://developer.android.com/training/keyboard-input/commands.html
An event listener is an interface in the View class that contains a single callback method. These methods will be called by the Android framework when the View to which the listener has been registered is triggered by user interaction with the item in the UI.
http://developer.android.com/guide/topics/ui/ui-events.html#EventListeners
Android soft keyboard does not create any events so there is no good way of listening for keyevents ... you can use add a TextWatcher ( http://developer.android.com/reference/android/text/TextWatcher.html ) to a hidden edittext.
http://developer.android.com/reference/android/hardware/input/InputManager.html
As per documentation this has a nested class
Nested Classes
interface -- InputManager.InputDeviceListener -- Listens for changes in input devices.
Just a lead, not sure about the usage though

Java View to Controller Observer

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.

Decoupling View from Controller in Java MVC Pattern

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

Categories