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.
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 need some way to deliver events that should be done only once from the ViewModel. Currently, I'm using LiveData for this.
Use case:
I'm building some intent and then I should deliver it to fragment. The problem is obvious, after rotate, I get old data and startAtivity runs once again.
I don't want to use some hacks with checks, etc. I'm sure there's should be the correct way to do such things.
The only way I've found is here: link - SingleLiveEvent.
So, is it a correct way to do such things?
What is the correct way to deliver UI dependent events from the ViewModel?
Is it a correct way to do such things?
Answer to this question is yes, if that does the job without leaking any objects at all than you've probably found right solution !.
What is the correct way to deliver UI dependent events from the
ViewModel?
Above solution you've found out is okay in your use-case, but if you're finding a solution that don't involve LiveData at all than i might be able to point it to one direction. Check out a solution below :
Let's say your ViewModel has a asynchronous method that you want to deliver result on UI.
Take a interface object of your result type that provides interaction between your ViewModel & Activity/Fragment, on your async method from ViewModel pass your LifeCycleOwner object and interface object as method parameter.
Now check in your method about your lifecycle events of your LifecycleOwner (i.e. activity or fragment instance here) and provide callback by interface on your UI.
So, now you can mark your result as null once delivered to UI.
It's bit of setup, but will work when you want solution without LiveData.
I have started a thread which connected to bluetooth device and streams data. I actually started this thread from a service(Thread not started from activity). So know I need to communicate to activity to show the list of input streams. I am not sure if event bus can provide a such a high frequently changing data. Can some one give me a better existing examples of how to use display the streams.
Please don't ask me for the source code.
I believe Event bus can be a good solution, also check bound services:
https://developer.android.com/guide/components/bound-services.html
I advise you to look into LiveData from the Android architecture components. You can observe the result from the activity, and it will "unsubscribe" for you when needed (onStop()). You can read about the advantages on the link I provided.
You could extend a LiveData and implement the logic inside it (like this example), or just use it to dispatch the updates, then observe it on the Activity. The postValue() method will ensure that it gets dispatched on the MainThread.
In the project, there are many modules. Each module may want to receive data emitted from other module/modules.
The problem trying to solve is, when we subscribe an observable A, this observable may have not been created yet. To solve this problem, two approaches are discussed:
Have a Observable Registry singleton. Every time when an observable is ready, put a pair into the Registry, and notify all modules that Registry changed. Each module will listen to this notification, and decide if it is a change it interested. If it is notified that the observable is ready, subscribe it. If the observable is removed, update the registry, delete corresponding pair, and notify modules, module unsubscribe it.
Rx implemented event bus. Take use of Subject: create a singleton Subject, then whenever an event or data or item need to be emitted, emit it from this subject. In your subscriber, you only subscribe on specific event, by using a filter on the subject.
The first approach looks very straightforward, and I cannot tell why it's not good. But it just doesn't look scalable to me. The second approach is the recommended way to replace otto/eventbus with Rx.
Any thoughts on these approaches?
For me the first approach is not that simple and too much to handle. The subscribers can subscribe to a topic and start receiving events whenever there is one for that topic and they would not know if there is a new event source as they don't care.
I use extended variant of version 2, which is RxHub library. It is quite flexible as allows different behavior per topic/tag.
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().