I have a question if there is any significal difference between using @Module
object without @Singleton
functions and @Module
class with @Singleton
functions.
So like:
@Module
object ApiModule {
@Provides
fun test()
}
@Module
class ApiModule {
@Singleton
@Provides
fun test()
}
Do I have to mark @Singleton
in object
?
With Dagger being an Annotation Processor often the simplest and easiest solution is to just have a look at the generated code.
I prepared a minimal sample to demonstrate:
class Foo()
class Bar()
@Component(modules = [ClassModule::class, ObjectModule::class])
interface FooComponent {
val foo: Foo
val bar: Bar
}
@Module
class ClassModule {
@Provides
fun foo() = Foo()
}
@Module
object ObjectModule {
@Provides
fun bar() = Bar()
}
If we take a look at the generated code we can see the following (I removed some irrelevant bits, just compile the above code yourself and look at the implementation if you want to see it all)
public final class DaggerFooComponent implements FooComponent {
private final ClassModule classModule;
private DaggerFooComponent(ClassModule classModuleParam) {
this.classModule = classModuleParam;
}
public static Builder builder() {
return new Builder();
}
@Override
public Foo getFoo() {
return ClassModule_FooFactory.foo(classModule);}
@Override
public Bar getBar() {
return ObjectModule_BarFactory.bar();}
public static final class Builder {
private ClassModule classModule;
private Builder() {
}
public Builder classModule(ClassModule classModule) {
this.classModule = Preconditions.checkNotNull(classModule);
return this;
}
public FooComponent build() {
if (classModule == null) {
this.classModule = new ClassModule();
}
return new DaggerFooComponent(classModule);
}
}
}
What you will notice is that Dagger creates an object for ClassModule
, but uses ObjectModule
with its static method directly. Does this matter? Well, creating a new object is slow, not so much that it really matters, but we don't need to reduce performance unnecessarily either. So if you can, you should definitely prefer object
or interface
as modules for better performance.
As for the scope, it really doesn't matter what your modules look like, it's the method signature that counts. Dagger looks at the return type of the method along with any annotation to it. So yes, of course you need to set a scope no matter what you use for your module, object
, class
, or interface
. Ideally you'd add the scope on the class itself, though, and use constructor injection to avoid modules altogether.
tl;dr class
Modules result in an additional object being created, so interface
or object
modules should be preferred if possible.