Hot questions for Using EventBus in otto

Question:

In most of the case, when dealing with case

  • User thread (AsyncTask) to perform background processing
  • Pass back calculated result back to Activity or Fragment
  • Activity or Fragment re-creation might happen before user thread finishes its background processing

So far, from many reliable sources, I can see the recommended way is using Retained Fragment

Sources

From time to time, I heard event bus libraries is good for handling relations between Activities, Fragments, and background threads. (Please refer to https://github.com/greenrobot/EventBus. It states that performs well with Activities, Fragments, and background threads)

I came across some really popular event bus libraries

I was wondering, when comes to handle relations between Activities, Fragments, and background threads, how is event bus approach different from Retained Fragment approach?

Which ways is a recommended way?


Answer:

The event bus and Otto are not "recommended ways" by the Android developer guide primarily because they are third party libraries to simplify the task. And I believe Otto is fairly new, so older guides obviously aren't using it.

I personally like Otto, it's what I use and I haven't had any problems with it so far. But of course, that's because it suited my use-cases.

I have an example on how I used Otto here.

EDIT from the future: if you need an event bus, greenrobot/EventBus is better than Otto. Also, in some cases, LiveData<T> is perfectly sufficient instead of using event bus (which instead of emitting events to anyone, only emits to subscribers).

Question:

Suppose the following scenario with classes A,B and an instance of a event bus (It can be the Guava event bus, by Google or the Otto event bus, by Squ.re)

class A{
    @Subscribe
    public void onSomething(B event){
        //do something
    }
}

A a = new A();
eventBus.subscribe(a);
eventBus.post(new B());
// onSomething is called, everything ok

a = null;
eventBus.post(new B());
// onSomething is called again

Now, if I run that (only tested with Otto) onSomething is called 2 times.

¿Will the event bus hold a reference to 'a' until unregister is called?

And more importantly

¿If for some reason I am unable to determine the moment in which 'a' will be null, then the event bus will hold a useless reference to the object forever (memory leak)?


Answer:

The event bus will hold a strong reference always. The answer to both of your questions is yes.

When you set a to null above you are only clearing the local reference. Both Guava and Otto maintain a strong reference and require explicit unregistration. You will see the above behavior in both event buses.

I strongly suggest you tie the registration of an object to something other than the clearing of a local reference. The Android activity and fragment lifecycle is an obvious choice and so are things like close and destroy-like methods on individual objects.

Question:

I am developing some feature in my app where I receive a push notification and if some screens of my app are running make some stuff in them like update some list, put a badge and other things.

Use of push notifications is mandatory, I know that websockets or other similar solutions are better for accomplish this feature but we can't use it due to backend restrictions.

To inform the screen we think in use a Event library like Otto or Eventbus.The point is that we want to show a notification only if no screen receive "the message". To solve this problem we first throught in send back a "ACK" event to the notification receiver to inform it that it must not show the notification.

To not make this, (and here is my question) are there some form in one of this libraries to know if some Object is subscribed to a concrete Event?


Answer:

It's possible, though you can't get the subscribers directly.

Otto

If you subscribe to the DeadEvent, you'll receive it every time there's an event without any subscribers:

@Subscribe
public void deadEvent(DeadEvent deadEvent) {
    if (deadEvent.event instanceof MyConcreteEvent) {
        // handle the concrete event
    }
}
EventBus

The event used here is NoSubscriberEvent:

public void onEvent(NoSubscriberEvent event) {
    if (event.originalEvent instanceof MyConcreteEvent) {
        // handle the concrete event
    }
}

Question:

I'm trying to use Mortar for a simple application that shows a list of items based on mortar-sample.

I'm using Retrofit/Gson to fetch meta-data of these items and Otto to deliver updates to the view once the items are downloaded. I'm also using Dagger for objects creation.

I've an ItemList class that implements ListView to disply the items in a list, and an ItemListScreen that implements mortar.Blueprint.

I wonder where is the best place to put the subscribing method that will update the adapter items? Currently, I'm placing it under ItemListScreen.Presenter but the subscribe method is never called!!

@Layout(R.layout.item_list_view)
public class ItemListScreen implements Blueprint {
    ...

    @Singleton
    public static class Presenter extends ViewPresenter<ItemListView> {
        ...

        @Subscribe
        public void onEvent(Event event){
            ItemListView view = getView();
            if(view == null) return;
            view.showItems(event.items);
        }
    }
}

Answer:

You don't have your presenter hopping on the bus.

bus.register(this);

Probably want to put that in the onLoad method and then unregister when the view is no longer being displayed.