对象模块中的 Dagger @Singleton

Dagger @Singleton in object module

我有一个问题,使用不带 @Singleton 函数的 @Module 对象和带 @Singleton 函数的 @Module class 对象之间是否存在任何显着差异。

很喜欢:

@Module
object ApiModule {

    @Provides
    fun test()
}
@Module
class ApiModule {

    @Singleton
    @Provides
    fun test()
}

我必须在 object 中标记 @Singleton 吗?

是的,如果没有@Singlton,那么每次您需要注入任何测试时都会调用一次该函数returns。如果你有 @Singleton,return 值将被 dagger 缓存并在每次需要时重复使用。

将 Dagger 作为注解处理器通常最简单的解决方案就是查看生成的代码。

我准备了一个最小样本来演示:

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()
}

如果我们看一下生成的代码,我们可以看到以下内容(我删除了一些不相关的位,只需自己编译上面的代码,如果您想查看全部,请查看实现)

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);
    }
  }
}

您会注意到 Dagger 为 ClassModule 创建了一个对象,但直接使用其静态方法使用 ObjectModule。这有关系吗?好吧,创建一个新对象是 slow,并不是很重要,但我们也不需要不必要地降低性能。因此,如果可以的话,您绝对应该更喜欢 objectinterface 作为模块以获得更好的性能。

至于范围,模块的外观并不重要,重要的是方法签名。 Dagger 查看方法的 return 类型 及其任何注释。所以是的,当然,无论您将什么用于模块,objectclassinterface,您都需要设置范围。 不过,理想情况下,您会在 class 本身上添加范围,并使用构造函数注入来完全避免模块。


tl;dr class 模块会导致创建一个额外的对象,因此 interfaceobject 如果可能,应该首选模块。