I'm trying to pass an event from a fragment to a dialog using otto. Unfortunately by the time the dialog is created the event has already fired and the #Subscribe method in my dialog and the data that was being sent gets passed over.
The data I'm trying to pass is an Object and an index (Best case) or a String (worst case) from a listview/ArrayList.
I know they have an #Produce method; but I don't understand how a method that takes no arguments helps in anyway or how I can get it to work.
Here's an example they provide
#Produce public AnswerAvailableEvent produceAnswer() {
// Assuming 'lastAnswer' exists.
return new AnswerAvailableEvent(this.lastAnswer);
}
For my newly created dialog this.lastAnswer; won't exist, it can't - that's what I'm passing in.So how do I get around this?
Side note:
I think the event bus, in it's current form is a bit of overkill since it's only communicating with my dialog. Later on I hope to use the event bus in more dialogfrag/fragment communication.
I've also asked same question for myself, when I was investigating Otto. And decided to read their site(http://square.github.io/otto/) more thoughtfully.
Here is their description under #Produce annotation:
...
Producers, like subscribers, must also be registered...
When registering, the producer method will be
called once for each subscriber previously registered for the same
type. The producer method will also be called once for each new method
that subscribes to an event of the same type.
You may only have one producer per event type registered at a time on
a bus.
So I think in time you register your producer, "lastAnswer" should be initialized.
And no parameters needed because you don't suppose to call your producer-method by yourself.
I hope it will help.
Related
I'm try to use event bus lib, I could not understand it's functionality and see multiple examples. Is it use only services class or use activity and fragment then is use activity what situation we use event bus in activity or fragment.
Instead of interface we can simply use EventBus .we can pass messages from one class to one or more classes. EventBus in 3 steps
Define
Register and unregister
Post Event
Define events:
public static class MessageEvent { /* your getter and setter */ }
Prepare subscribers: Declare and annotate your subscribing method, optionally specify a thread mode:
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
/* event fire here when you post event from other class or fragment */
};
Register and unregister your subscriber. For example on Android, activities and fragments should usually register according to their life cycle:
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);//Register
}
unRegister
#Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);//unregister
}
Post events:
EventBus.getDefault().post(new MessageEvent());//post event
You can consider EventBus as a lightweight communication channel for passing data within activities, or services, or fragments or between any of them.
Think of EventBus as an underlying layer in your app which is independent of any active activities or services or fragments and their lifecycle.
The main concept on which an EventBus works is that you subscribe to events in either an activity or fragment or service or any components like that and whenever the EventBus has a specific event of the type you subscribed, it notifies your subscribed method in that component and you can perform any task there based on the event that you have received.
Triggering an event is easy and you can do it from any area of your app by just passing a specific event (which is basically a POJO class, let's say MyEvent) to the EventBus, and the bus will handle the rest and correctly deliver it to the appropriate receiver/s.
I would recommend you to try out EventBus 3 from GreenRobot, and go through their documentation here to incorporate their library n your code. I have been using the same without any problems.
EventBus 3 by GreenRobot
Hope this helps.
Mostly you shouldn't. In general its a hack for when you misarchitected your program and can't easily pass data from one point to another due to how your app is encapsulated and what objects are known at what levels. It can cause real spaghetti code where its difficult to figure out what code will actually be called when an event occurs. You shouldn't be writing your code around having an event bus, it should be a last resort if you can't refactor things to work the correct way.
One of the advantages of events is that you can pass objects around to 'somewhere', and you don't need to know where it is picked up. This makes it easy to push your activity or fragment state to a controller class, and then use events sent from this controller back to the activity or fragment.
Because of events, the controller doesn't need to know if the receiving end is an activity or a fragment. This makes it very easy to switch one for the other. On the other hand this also makes it easy to put the controller somewhere else. Like first you have it as an instance in the application class, and then you move it to a service.
I wrote an article with a very concrete example on how you can use events to deal with the Android life cycle as described above: https://medium.com/#JuliusHuijnk/beating-the-android-life-cycle-d00a2f3ed88
I am developing an application in which I am using retrofit library for calling the web services . After calling web-service a callback return Response then I am passing the Response to the next activity. I want to know the best approach for this .
I am new in memory related problems please correct me if I am totally wrong.
Shall I make a new class then pass a weak reference to that class and call the function from that class on the main activity.
Or
I shall register a new event on event bus and when the callback returns the object ,fire the event and call the function.
Please consider what is good to avoid Memory Leaks.
Saving callbacks/listeners in weak references is not a good idea. See
Pros and Cons of Listeners as WeakReferences
Are anonymous listeners incompatible with weak references?
You can "broadcast" results of asynchronous operations (Network calls in your case) on completion using event bus, and have other objects (Views, Fragments, Activities) register to event bus. Points to note:
Listeners must always un-register properly, else its a memory leak.
You'll need to create a new class for each event type. Soon this number will grow.
Inheritance and Event bus do not play well. There is no proper "overriding" of listening methods possible.
Perhaps some other object also requested the same data. Since EventBus broadcasts to all, listeners might get multiple events of same type, at unsuspected timing.
Particular to Retrofit usage, if you do requests asynchronously as:
GitHubService service = retrofit.create(GitHubService.class);
Call<List<Repo>> repos = service.listRepos("octocat");
repos.enqueue(myCallback)
Then you must remember to cancel all calls that a component has made, when the life-cycle of component is complete. I.e onDestroy() of Activity, onDetach() of Fragment, onDetachFromWindow() of View:
repos.cancel();
I am writing a code, where I will use more onClickListener for one View but I want it to have only one onClickListener at time.
So my question is: Is it enough if I always call myView.setOnClickListener(MyListener) or do I need to call myView.setOnClickListener(null) always before I set a new listener to the view?
The documentation says only that it registers a callback, doesn't say anything about the previously registered callbacks.
Thank you for your answer!
So my question is: Is it enough if I always call
myView.setOnClickListener(MyListener)?
yes it is enough. the setter, as the name says, sets (assigns) the reference you are providing as parameter, overriding any precedent assigned references.
The documentation says only that it registers a callback, doesn't say
anything about the previously registered callbacks.
It doesn't because the name implies already it
I've got 2 running classes registered for EventBus events - instance A and instance B. Both of them have implemented onEvent(SampleEvent event) method for receiving EventBus.post(new SampleEvent(int foo, String bar)); from a place C. So far so good.
But there is a time when I need to post SampleEvent from B to A. Is it possible to tell B that it shouldn't process SampleEvent sent by itself, or I need to do workaround like setting a flag in SampleEvent?
You could try to extend SampleEvent for exmaple SampleEventToA than you check within B by using reflection:
if (! event instanceof SampleEventA){
//do things here
}
Found this issue on otto EventBus: Derived events from super event will also call the subscriber of the super event. This would be a possible OO solution!
https://github.com/square/otto/issues/83
I'm trying to Subscribe and Post from the same fragment, but I'm getting this error when i try to register the fragment:
...(my method) has #Produce annotation but requires 1 arguments. Methods must require zero arguments.
on
BusProvider.getInstance().register(this);
So i guess it's not possible, but maybe there is an alternative without additional interfaces.
Thanks in advance!
Methods annotated with #Produce must not take any arguments. They should just return the event object.
"I'm trying to Subscribe and Post" suggests you probably need to change it to #Subscribe annotation instead.
For posting events, just use post(). #Produce is meant for returning the latest value of an event.