19
votes

When using Dagger, I found that I'm getting multiple instances of a singleton when I inject it wherever I need it. I've annotated the class and the provides method with @Singleton. Can anyone think of why this is happening?

Edit:

If it helps, I have followed the same structure for my app as the sample application in Dagger's GitHub (https://github.com/square/dagger/tree/master/examples/android-activity-graphs). I'm trying to get the Singleton in the base activity and a couple of third party classes provided using @Provides at the custom Application class. Is it because I'm plus-ing modules at each activity to the original object graph?

(PS : I'm new to Dagger and DI in general, so I'll be grateful if you could provide an explanation so that I may learn. Thanks.)

1

1 Answers

39
votes

@Singleton, in Dagger 1.x, acts differently than you might think. The JSR-330 spec definition in the @Singleton javadoc is "one per graph" and that is how Dagger interprets it.

So if you have something that is marked as @Singleton, and it is materialized in your application graph (as opposed to a shorter-lifetime graph), then you get one instance per application.

If you have an item annotated @Singleton that's in the modules you use to configure your activity graph (i.e., that is obtained from the part of a graph specified by a module used in the plus() operation) then you will get one-per-activity-graph.

If you need something to be once-per-application, you need to make sure it gets created as a part of the application graph. You can do this in one of two ways. Either explicitly provide it with an @Provides method from your application module(s), or you can list it as a one of the classes in @Module(injects=...) in an application module.

(If you do not mark it with @Singleton than you will get one per injection site.)

So remember, the graph created by plus() is seen as a separate graph that points to the graph from which it was spawned, and wraps it, can access instances within it, but is not the same graph.

Note - Dagger 2.x improves this, and supports custom scoping annotations, though the mechanism is similar, with one graph (component) per scope annotation, with a parent/child relationship between graphs of wider/narrower lifetimes