one object if injected into 2 subcomponents under same custom scope, every time new instance is created of that object. I want same instance to be passed to all subcomponents
this is the module
@CustomScope
@Module
public class EventBusModule {
PublishSubject<Boolean> bus = PublishSubject.create();
@CustomScope
@Provides
public PublishSubject<Boolean> provideRxBus() {
return bus;
}
}
these are my subcomponents
@Module
public abstract class ActivityBindingModule {
@CustomScope
@ContributesAndroidInjector(modules = {HomeActivityModule.class,
EwayBillFragmentProvider.class, EventBusModule.class})
abstract HomeActivity mainActivity();
@CustomScope
@ContributesAndroidInjector(modules =
{EwayBillDetailActivityModule.class, EventBusModule.class})
abstract EwayBillDetailActivity ewayBillDetailActivity();
}
these subcomponents are written inside ActivityBindingModule which is added to my application component. Now I want same instance of my PublishSubject object in both the subcomponents, I am fairly new to dagger and I want to know what am I doing wrong?
You'll need to move your
bus
into Application scope, which typically means annotating it with@Singleton
(if that's how you've annotated your top-level component that ActivityBindingModule is installed into). You'll also need to move your method into a Module installed on that component, which might as well be ActivityBindingModule.First, an explanation of what you see:
@ContributesAndroidInjector
creates a subcomponent for each object it annotates, marked with the scope annotations and modules you put on the@ContributesAndroidInjector
method and annotation, so that your call toAndroidInjection.inject(this)
inonCreate
creates a new instance of that subcomponent and uses it to inject the Activity instance.Your
@CustomScope
(which may be better-named as@ActivityScope
here) on the@Provides PublishSubject<Boolean>
method means that your instance will share the same lifecycle as the component that is also annotated with that scope annotation. Here, that's each automatically-generated subcomponent. Furthermore, because your Module is a non-abstract class with public no-arg constructor, Dagger will automatically create a new instance every time it creates a Component that requires your module, which means a differentbus
for each Activity instance. (It can't and won't do so for Modules that are abstract classes or interfaces.)You want your
bus
object to be the same instance between Activities, which means that@CustomScope
/@ActivityScope
is much too short: You want the object to outlast any single Activity's lifecycle. This means that you'll either need to store the instance elsewhere and pass it into each Activity, or you'll need to store the instance in your Application component itself. I'd recommend the latter, because this is one of the problems Dagger was created to solve, and because this will automatically make the bus available across your application: Dagger subcomponents inherit access to all of the bindings in their parent components. That gives the code you see above. (Note that by doing this, you'll keep the instance of PublishSubject around even when there is no Activity showing, when your application is running in the background; if you want the same instance between Activities, this is a necessary consequence, but choose this carefully to avoid too much background memory use.)One alternative is that you keep track of the
bus
instance yourself, and insert it into each Activity. You could do this by having your Module take a parameter, but that is rather tricky to do with dagger.android (which powers@ContributesAndroidInjector
). You could also write a@Provides
method that delegates to a WeakReference, or use the@Singleton
technique above to write a holder that temporarily stores yourbus
between Activities. However, because Android keeps a lot of control over your transitions between Activities and the Activity lifecycle, it may be the best you can do to keep thebus
in@Singleton
scope as I did in the code above.