Is it good practice to use Otto event bus bi-directionally?
I mean, send events from controller to view, and view to controller?
Or is it just meant to publish results meaning its purpose is only events from controller to view?
Thanks
Good question. Here is my thoughts on this. I use Otto for a while and use it bi-directionally. From my experience there is nothing against doing this. I have just defined couple of rules helping me keep everything under control.
One-to-many pattern must be confirmed. I mean here, that one producer should normally notify multiple subscribers. Of course, at different point in time there can be zero or more subscribers. But if you have a case, where by-design maximum number of subscribers is just one, then you trying to dispatch rather a "command", than an "event". For such cases I would use a direct call instead of posting a event.
Another thing to avoid should be a situation, when one event triggers another event, which, in turn, triggers first event again. You can run in infinite event chain here. This might happen when same class has the both subscriber and producer methods. If I have such classes, I try to keep those methods as independent as possible.
And of course I always use Android components' lifecycle to register and unregister publishers and subscribers dynamically. I start with onResume() and onPause() methods and, if needed, I'm going up to onStart() or even onCreate().
Related
I'm working on this project in Android in which an aspect requires a CountdownTimer with a foreground service. A few other answers on Stack Overflow mentioned that LocalBroadcastManager would be suitable for my needs.
The documentation in Android Developers, however, mentions that it has been deprecated. Any suggestions on what I should use in its place? The documentation mentioned about using LiveData, but I was wondering if there are any easier alternatives.
LocalBroadcastManager is basically an event bus with a lot of unnecessary ceremony around Intents and intent filters. So one replacement is easy, and functions quite similarly: you can use any event bus library. greenrobot's EventBus is a popular choice (here's a guide for it) and Guava also has one, if you're already using Guava (but Guava is pretty heavy to include just for an event bus).
But event buses suffer from the same problems that LocalBroadcastManager does that led to it being deprecated: it's global, it's not lifecycle-aware, and as your app gets larger, it becomes much more difficult to reason about the effects of a change to an event. For cases of observing data, LiveData solves this quite nicely because it's lifecycle-aware, so you won't get change notifications at the wrong time (like before your View is set up, or after onSaveInstanceState) - but it'll handle delivering the change notifications when you're in the right state again. It's also more tightly scoped - each piece of LiveData is accessed separately rather than having (typically) one event bus/LocalBroadcastManager for the entire app.
For cases where it's more of an event rather than a piece of data being changed, you can sometimes convert it to a piece of data. Consider if you have "login" and "logout" events - you could instead create a LiveData that stores an Account for logged-in users, and becomes null when the user is logged out. Components could then observe that.
There are certainly cases where it really is difficult to convert it to a piece of observable data (though I can't immediately think of any examples that would typically be used with an event bus patten). For those, consider writing your own listener interface, similar to how on-click listeners work.
For your example of a countdown timer, I think LiveData is a pretty straightforward solution, and will be much easier than an event bus or even LocalBroadcastManager would be. You can just have a LiveData of the timer's current value, and subscribe to it from whatever needs to show the value.
I am currently researching for better ways to handle events in my app.
Currently I have multiple listeners that are subscribing and unsubscribing to interesting objects on different events.
E.g. on a button click a listener is created, that listens on a client object, if a operation succeeded (in that case it automatically unregisters itself) or if a non fatal error occurs (in that case it automatically retries the operation).
The client object in turn is starting a android service that can emit different status events, that should result in the user interface updating itself or alternatively show notifications, if the app is currently not visible.
In my app I have a really big listener clutter, that is not easy to follow and that is not working on all occasions.
To resolve this issue I would like to implement a event bus with RxJava that hopefully reduces the complexity of my application.
The problem:
Is it possible with RxJava to have a fallback observer for a observable, to react to events, if no other observer is available?
E.g. All activities/fragments register themselves to get informed about certain events, so they can update the UI, if necessary.
When a activity/fragment is created/destroyed it automatically registers/unregisters itself from the event bus.
If the app is now in background, there should be no observers registered anymore. In that case only I would like to use a fallback observer that is handling those events.
I would like to achieve the following:
If in foreground: On event, update the UI.
If in background: On event, show toast / notification.
In my opinion your app shouldn't show anything when it's in the background (user is not interested in it anymore, or is doing something else, so don't spam him with toasts (as he probably would not even know which application raised this toast)).
However,
You can solve this problem with Subject. Let say you have MyServiceErrorHandler class with PublishSubject> inside, so every time there is some part of UI is visible and capable of showing error is should be subscribed to this subject. Then you can expose method like onError(Throwable t) which will call subject.hasObservers(). If yes it pushes data to subject (so it will emit an event to currently subscribed UI) if no you can do some fallback thing (like displaying toast/notification/logging something/etc). This solution is however error prone to rotation as you may receive your result while screen is rotating (thus not subscribed yet)
You can extend this approach a little bit and use a BehaviourSubject which will replay it's last event for every subscriber (pretty handy in case of screen rotation). So you're posting event to this subject even though there are none subscribers, and when user opens this app back again (and one of your UI element will subscribe) it will receive last event with error (so you can show it properly). But in that solution you would need a little bit more logic to clear this subject in case of obsolete/already consumed errors (to prevent it from showing on every rotation/etc).
There are several situations in my codebase where a stream I'm subscribing to will only ever emit one result and as such it makes sense to use rx.Single rather than rx.Observable. The documentation for Single says the following:
A Single will call only one of these methods, and will only call it
once. Upon calling either method, the Single terminates and the
subscription to it ends.
With a traditional Observable I capture a reference to the Subscription so that I can unsubscribe at an appropriate time and not cause memory leaks:
Subscription s = getObservable().subscribe(...);
subscriptions.add(s);
subscriptions.clear();
My question is whether this is necessary with a Single or whether due to the fact that the subscription ends immediately it could be left simply as:
getSingle.subscribe(...);
Without any negative repercussions of references being held onto into the subscriber.
Single doesn't tell you anything about how long it will be running.
Since you're targeting Android, the answer is yes, you should keep the subscription and unsubscribe.
Imagine you're switching Fragments/Activities and a long running SingleSubscribers's onSuccess is called. So the best time and space is probably in onPause(), but it depends on your context.
You might run into NullPinterExceptions, Adapters being filled multiple times or similar problems if you don't unsubscribe.
Any reason why you need to cleanup the subscription on Observable?. Observable by design once that the observer has all items is automatically unsubscribed.
And then, since the instance is not reference anymore the GC at some point will clean up for you.
You can see in these example how the subscription is unsubscribe after onComplete is reach.
https://github.com/politrons/reactive/blob/master/src/test/java/rx/observables/creating/ObservableSubscription.java
I have many Activities which raise background tasks; the Activities will pass themselves in as having implemented a listener callback, so that the background tasks can raise an event on the Activities. The Activities in turn can show something on the UI to indicate that a background activity passed or failed.
Alternatively, I could use an EventBus, wherein I get the Activity to register itself as a listener/subscriber. I can have a background tasks raise an event on the EventBus and the Activity listening to it can handle it.
What are the advantages of one over the other? When would you use one over the other? (Code cleanliness? Performance? Caveats?)
Follow up - I did end up using EventBus. The code is definitely a lot cleaner and there aren't callbacks hanging out everywhere. The IDE (IntelliJ) thinks that the onEvent methods are unused, so I created an annotation
#Target({ElementType.METHOD})
public #interface EventBusHook {}
and placed it over my onEvent methods. Then Alt+Clicked on it and asked IntelliJ to not treat it as unused.
#EventBusHook
public void onEvent(MyEventType myEventType){
I disagree with #nnuneoi's answer.
Event bus has just one single advantage: it allows for communication between components which are "unaware" of each other's existence.
And there are several disadvantages:
The components become loosely coupled by dependency on both event bus and specific event type
The coupling described in #1 above is not strong
The coupling described in #1 above is not evident
Event bus introduces performance overhead over simple callbacks
If event bus holds a strong reference to subscribers (as is the case with e.g. GreenRobot's EventBus), then unregistered subscribers will cause memory leaks
Given all these disadvantages, simple callbacks should be the default implementation choice.
Event bus should be used only when direct coupling is not desired or hard to implement. For example:
Sending events from Service to Activity
Exchanging events between independent Fragments
Application wide events (e.g. user login/logout)
If the communicating components are already "aware" of each other's existence, there is no need for them communicating via event bus.
Benefits of using EventBus:
Your code will look much more clean
Your code will become more modular which will allow you to easily create test case for your code
Avoid memory leaks from bad object references which lock the object and does not allow Garbage Collector to clean it up
Could have more than one receiver a time, that it much like broadcasting
Simplify multiple interfaces into a single one, EventBus
In an interface class, you need to override every single method in the class that is inherited. With EventBus, you can listen for just an event that you really want
But bad part is you might be a little bit more headache with the function declaration since IDE couldn't help you with auto-complete.
My suggestion is, if you find that you have to create a custom listener, then please consider EventBus, it might be a better choice for most of (if not all) of your requirements/cases.
Anyway, it is all your choice after all =)
You should check if your event is globally unique on the semantic view. Either an subscriber is interested in the event or not. If not he shouldn't subscribe.
Event-Bus mechanism is right if you really have a publisher-subscriber relationship. The event must be totally independent of the receiver.
So a subscriber that discard the event for any reason of responsibility ("I am not responsible the event even if I am registered") is a strong indicator that using an Event-Bus is wrong. Then you should consider using dedicated listeners.
I would go with the EventBus because of the loose coupling and cleaner code. Also, the fact that using an EventBus such as Greenrobot automatically does all the boilerplate for me and allows me to register & deregister observers right from Activity Lifecycle methods (onStart and onDestroy|onStop) is great. Implementing callbacks and still managing to control Activity lifecycle management for those callbacks is an unnecessary headache and involves a lot of unnecessary boilerplate.
Also, apparently all garbage collectors think weak reference is great-Event bus gives your observers and components exactly that. Its the basis of the Observer pattern.
I'm studying a way to handle activity lifecycle and retain the state/progress of users app, then I found the otto/eventbus solution.
But after some research i can't figure out how to handle a particular case. So, what happens if my worker thread (async) finishes between the onpause/oncreate of my activity/fragment, it won't deliver the data? I'm trying to find an answer or create a project to test this, but just with my tests i can't be sure.
Am I missing something or the bus won't deliver the data? If it won't deliver the result how to handle that?
Sorry for my awful english.
Events are only passed to subscribers that are active at the time of posting.
To deliver an event to subscribers later on, store the object you're posting to a model object of sorts and add a #Produce getter for it. When a new subscriber for that object is registered, it gets its initial event from this #Produce getter.