Dagger @Singleton в объектном модуле - PullRequest
0 голосов
/ 04 марта 2020

У меня есть вопрос, есть ли существенная разница между использованием @Module объекта без @Singleton функций и @Module класса с @Singleton функциями.

Так как:

@Module
object ApiModule {

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

    @Singleton
    @Provides
    fun test()
}

Нужно ли отмечать @Singleton в object?

Ответы [ 2 ]

1 голос
/ 05 марта 2020

Поскольку 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 с его методом stati c. Имеет ли это значение? Что ж, создание нового объекта медленно , не так много, что это действительно имеет значение, но нам также не нужно без необходимости снижать производительность. Поэтому, если вы можете, вам определенно предпочтительнее использовать object или interface в качестве модулей для повышения производительности.

Что касается области действия, то на самом деле не имеет значения, как выглядят ваши модули, это сигнатура метода, которая на счет. Кинжал просматривает возвращаемый тип метода вместе с любой аннотацией к нему. Так что да, конечно, вам нужно установить область независимо от того, что вы используете для вашего модуля, object, class или interface. В идеале вы бы добавили область видимости к самому классу и использовали бы инжектор конструктора, чтобы вообще избежать модулей.


tl; dr class Модули приводят к созданию дополнительного объекта, поэтому предпочтение отдается модулям interface или object, если это возможно.

0 голосов
/ 04 марта 2020

Да, если у вас нет @Singlton, то функция будет вызываться один раз для каждого раза, когда вам нужно ввести какой-либо тестовый результат. Если у вас есть @Singleton, возвращаемое значение будет кэшироваться кинжалом и использоваться повторно каждый раз, когда это необходимо.

...