Проблема области действия Dagger 2, определите модуль дочернего фрагмента. результат: привязка не разрешена для интерфейса - PullRequest
0 голосов
/ 24 января 2019

Я хочу использовать Dagger для создания модуля для AFragment с дочерними фрагментами (X ... Z) FragModule.

Начиная с ActivityBindingModule, я определяю зависимые модули примера действия

/* ActivityBindingModule.java */
@Module
public abstract class ActivityBindingModule{
    @NonNull
    @ActivityScoped
    @ContributesAndroidInjector(modules = {
            AFragModule.class,
            BFragModule.class
            // ... fragment modules
    })
    abstract MainActivity mainActivity();
}

В AFragModule я определяю его зависимые от дочернего фрагмента модули.

/* AFragModule.java */
@Module
public abstract class AFragModule{
    @NonNull
    @FragmentScoped
    @ContributesAndroidInjector(modules = {
            XFragModule.class,
            YFragModule.class
            // ... child fragment modules
    })
    abstract AFragment providesFragment();
}

In(X ... Z) FragModule, я определил методы поставщика его зависимых объектов.

/* XFragModule.java */
@Module
public abstract class XFragModule{
    @FragmentScoped
    @ContributesAndroidInjector
    abstract XFragment providesFragment();

    @ActivityScoped
    @Binds
    abstract XContract.Presenter providesPresenter(XPresenter presenter);
}

Я хочу, чтобы модули (X ... Z) FragModule находились в пределах AFragModule.И (X ... Z) презентаторы FragModules находятся в одной области для связи между докладчиками.

Сама реализация XPresenter использует инжектор конструктора с параметрами @Singleton (например, источниками данных)

Я получаю следующую ошибку с вышеуказанными областями:

Cause: binding is not resolved for XContract.Presenter: ProvisionBinding{contributionType=UNIQUE, key=XContract.Presenter, bindingElement=Optional[providesPresenter(XPresenter)], contributingModule=Optional[XFragModule], kind=DELEGATE, nullableType=Optional.empty, wrappedMapKeyAnnotation=Optional.empty, provisionDependencies=[DependencyRequest{kind=INSTANCE, key=XPresenter, requestElement=Optional[presenter], isNullable=false}], injectionSites=[], unresolved=Optional.empty, scope=Optional[@ActivityScoped]}

РЕДАКТИРОВАТЬ: Я также хочу проверить мое понимание области действия: «я думаю», я понимаю следующее

@ Singleton> @ActivityScope> @ FragmentScope

  1. Области не могут зависеть от той же или меньшей области видимости, напр.@ActivityScope не может зависеть от @ActivityScope или @ FragmentScope

  2. Области действия могут зависеть от большего объема.ех.@FragmentScope может зависеть от @Singleton, @ActivityScope отмеченных методов.

1 Ответ

0 голосов
/ 24 января 2019

В вашем конкретном случае похоже, что Dagger не может найти привязку для XPresenter;у вас есть утверждение от @Binds XContract.Presenter до XPresenter, но на основании вашего случайного упоминания о "самой реализации XPresenter" похоже, что вы можете пропустить утверждение вроде:

@Binds
abstract XPresenter providesXPresenter(XPresenterImpl presenterImpl);

Scopes может зависеть от той же области действия: элементы в @ActivityScope могут зависеть от @ActivityScope, но не от @FragmentScope.Если вы попытаетесь зависеть от объекта @FragmentScope от @ActivityScope («расширение, расширяющее область действия»), Dagger предотвратит это и опишет компоненты, в которых вы можете найти эту инъекцию.

Однако вы, скорее всего, такжестолкнуться с проблемой, что компонент @FragmentScope не может содержать другие компоненты @FragmentScope, что является проблемой, учитывая, что @ContributesAndroidInjector обязательно создает новый подкомпонент, который принимает область и модули, перечисленные в методе.Вам нужно будет изменить выбранные аннотации области, например, , создав и используя @ParentFragmentScope и @ ChildFragmentScope .Это также важно, потому что ваш @ChildFragmentScope Fragment XFragment может внедрять объекты, которые совместно используют жизненный цикл экземпляра субкомпонента XFragment, экземпляра субкомпонента AFragment, экземпляра субкомпонента MainActivity или корневого компонента @Singleton.

OfКонечно, вы, вероятно, захотите назвать их в соответствии с вашим вариантом использования, например, @FullScreenFragmentScope или @TabFragmentScope или @OptionalFlowFragmentScope;Вы также можете выбрать внешнюю область, чтобы @FragmentScope оставался, а внутреннюю область - @SubFragmentScope и т. д., что может быть особенно полезно, если у вас есть модули многократного использования, которые уже используют @FragmentScope.Дело в том, что модуль многократного использования, который использует @FragmentScope, не будет ясно, отслеживает ли он жизненный цикл AFragment или жизненный цикл XFragment, поэтому вам нужно будет прояснить это.

...