From the dagger 2 Documentation I noticed that you can have a @Singleton
annotated class. What is the purpose of marking a class as @Singleton
as I have tried to do this in my code but a singleton object is NOT produced. I'm not clear on what use marking my class with this annotation serves.
From the documentation please focus on the following statement:
The @Singleton annotation on an injectable class also serves as
documentation. It reminds potential maintainers that this class may be
shared by multiple threads.*
@Singleton
class CoffeeMaker {
...
}
UPDATE: After reviewing froger_mcs answer I see that in Dagger 2 you can provide injections either by a module OR by a constructor injection. So the following class, although not in a module, can be injected:
@Singleton
public class MyClass {
@Inject
public MyClass() {
}
}
In this version the constructor is injected for us and in an Android activity you would just do the following and it will get provided:
@Inject
MyClass myClass;
//then in onCreate actually inject(this) from your graph of course.
@Singleton
(and any other scope annotation) makes your class a single instance in your dependencies graph (it means that this instance will be "singleton" as long as Component object exists).
In short - everytime you're injecting @Singleton
annotated class (with @Inject
annotation) it will be the same instance as long as you inject it from the same Component.
For more I'm referring my blog post about how @Singleton
and other scopes annotations works in Dagger 2: http://frogermcs.github.io/dependency-injection-with-dagger-2-custom-scopes/
@Singleton
does not really create a Singleton, it is just a Scope
, it is advised to not use @Singleton
as it is misleading, it gives the impression that we are infact getting a Singleton, but we are not.
Let's say you annotate your database dependency with @Singleton
and link with a Component
, now let's say that you initialise this Component
in Activities
A
and B
, you will have different instances of your database in your two Activities
which is something most people don't want.
How do you overcome this?
Initialise your Component
once in your Application
class and access it statically in other places like Activities
or Fragments
, now this could soon get out of hand if you have more than 20 Component's
as you cannot initialise all of them in your Application
class, doing so will also slow down your app launch time.
The best solution according to me is to create a real Singleton
, either double checked or of other variants and use this statically as getInstance()
and use this under @Provides
in your Module.
I know it breaks my heart too, but please understand that @Singleton
is not really a Singleton
, it's a Scope
.
Well you can manually create an annotation,which will help to create a singleton object.
@Scope
@Retention(RetentionPolicy.CLASS)
public @interface MyApplicationScope {
}
When @MyApplicationScope
annotation is added with @Provides
annotation than it makes dagger to create an object only once and use same object in future. Do remember to add this annotation to the component interface also otherwise you will get the scope related error during compilation.
If you are using @Singleton
annotation then you may end up creating the new objects every time when you will create your component with .build()
.
@Singleton is inherit @Scope, so in documentation says
Identifies scope annotations. A scope annotation applies to a class
* containing an injectable constructor and governs how the injector reuses
* instances of the type. By default, if no scope annotation is present, the
* injector creates an instance (by injecting the type's constructor), uses
* the instance for one injection, and then forgets it. If a scope annotation
* is present, the injector may retain the instance for possible reuse in a
* later injection. If multiple threads can access a scoped instance, its
* implementation should be thread safe. The implementation of the scope
* itself is left up to the injector.
<p>In the following example, the scope annotation {@code @Singleton} ensures
* that we only have one Log instance:
*
* <pre>
* @Singleton
* class Log {
* void log(String message) { ... }
* }</pre>
You get the point right? whatever annotation you use or you create a custom one, and they inherit from @Scope it will ensure as singleton.