Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Advantages of injecting Otto event bus instead of using static singleton

In my Android apps i'm using Otto as event bus and Dagger for dependency injection.

In the userguide of Otto and in many blog posts it's recommended to use injection to get a bus singleton. I have done that for some time, but lately i'm getting more doubtful if injecting the bus has any advantages over using a simple static singleton.

With injection i have to inject every custom View or ViewHolder that i want to be able to post UI events on the bus. Especially with dagger it seems a bit clumsy to inject every class where i need the bus. Sure, i could pass the bus by constructor or setter method, but that can be kind of clumsy too if you think about an adapter with many different view types for example.

And i don't see any advantages in injecting the bus. In case of Otto a concrete implementation is injected (an instance of Bus) and that will never change. Wrapping Otto for de-coupling does not make any sense if think, because of the way subscription works.

So, does anyone see any advantages of injecting Otto that i don't see?

like image 845
Daniel Niedermühlbichler Avatar asked Jul 16 '15 19:07

Daniel Niedermühlbichler


1 Answers

In my opinion, you should definitely wrap the event bus in your own class and use dependency injection techniques in order to pass it to clients.

enter image description here

There are several advantages to this approach over simply obtaining a reference through a call to static getInstance() method:

  • Your dependencies become explicit. When you obtain references to objects through static calls the dependencies are hidden inside implementation of the clients, which make the code fragile and harder to understand.
  • Will be easier to switch to a different implementation of event bus if such a need arises.
  • Injected dependencies are easier to mock in tests
  • The fact that dependency injection techniques introduce some degree of struggle is actually a good thing - if you're struggling, this is often an indication that you are doing something wrong. In your case, I suspect that you're abusing event bus.

I say that it is possible that you're abusing event bus because I don't really see why would you need to have a reference to it in View subclasses. I'd guess that you post notifications about user interactions to event bus, and then subscribe Activity or Fragment to event bus in order to intercept these events. Event bus is a wrong tool in this case (even though it works great).

The reason why event bus is a wrong tool in this case is because Fragments and Activity can have a direct access to the contained View objects. You can get references to these Views and register Fragments and Activities as listeners. No need to decouple anything here.

On contrary: think about a case where you go and refactor your Views in such a way that nothing being posted to event bus anymore (say, business requirements changed). Since Views notifications are only loosely coupled to containing Fragment or Activity through event bus, it is very probable that you'll forget to remove the events handling logic from Fragment and Activity, thus leaving "dead code" behind. This gets messy very quickly.

The better practice would be to use Observer design pattern and let Views notify Activities and Fragments directly, and only when handling involves another component (which can't be easily reached from Fragment and Activity; e.g. another Fragment or Activity) will these components post events to event bus. If you follow this approach, you will need to have a reference to event bus in "top level components" only, and no struggling will be involved.

P.S. I have recently published a blog post which introduces some best practices for dependency injection in Android.

like image 197
Vasiliy Avatar answered Sep 22 '22 00:09

Vasiliy