A few weeks ago, I made a post about how to make an event bus with RxJava. While this solution works, it goes against the coding style encouraged in the reactive programming model. Instead of passing around events, I could expose the Observables so that I can publish or subscribe directly to the source. It was suggested to me that I try out Dagger, as it does exactly what I want.
I had never used Dagger prior to this, but it’s simple to get started. I made a module, which provides the implementation for my Observables. Then I created a component, which uses the module I made to get my Observables. Dagger will create the implementation of my component, and with that I get access to my Observables.
How does it work?
I created a sample GitHub project to demonstrate my solution. You can see the Dagger module below.
Since I’m using the same class for each Observable, I need to use the
@Named annotation to differentiate them. I’m also using the
@Singleton annotation to ensure that I only ever have one instance of each Observable. If a different instance was returned each time, this would be useless. I need the publisher to communicate to the subscriber on the same Observable instance.
To use this Dagger module I created the following Dagger component.
Similar to the module, I have to use the
@Singleton annotation so that I only have one instance of my Observables. In fact, it won’t compile without this, because the module would be using a different scope than the component.
@Singleton to my component confused me though. When I set the
@Singleton annotation on the providers in my module, it made it so there’s only a single instance. But, that same annotation on my component does not have the same effect. I expected that if I called
DaggerBusComponent.builder().build() it would always return the same instance. This is completely wrong though. If you want to share instances of your objects across your application, you either need to make your own singleton class to store it, or extend
Application and store it there.
I chose to store it in my
App class, seen below.
Now I can use this wherever I want, like so:
Lastly, to manage my subscriptions I created a CompositeDisposable in my
Below is the final result, you can see the top fragment is subscribed to the bottom, and the bottom to the top. When a button is tapped from one side, it sends a message to the other.
Now that I’m exposing the Observables, I don’t have to cast objects or check their types anymore. Memory leaks are still a concern though, and having to keep track of each subscription feels a bit clunky. I considered making my own Observable that you can subscribe to, attached to a lifecycle (like a Fragment or Activity). The issue is that then my subscribers need to be listening to the lifecycle events. So my Fragment would need to have its own LifecycleObservable that each subscriber is watching, so they know when to pause, resume, and unsubscribe (in onDestroy).
If anyone has an elegant solution to Subscriptions being attached to the lifecycle I would love to see it. There is a library called RxLifecycle which is close to what I am looking for, but not quite. It allows you to bind your Observables to the lifecycle, but I actually want my Subscriptions bound to the lifecycle. My Observables are bound to the lifecycle of the application, but their Subscriptions need to be bound to Activities and Fragments.