Ответ 1
Короче говоря, вы должны переопределить вызов seedInstance
в Builder (который является абстрактным классом, а не интерфейс) для предоставления других необходимых вам модулей.
edit: Прежде чем вы это сделаете, проверьте и убедитесь, что вам действительно нужно передать этот модуль. Поскольку Дэймон добавил в отдельном ответе, если вы создаете определенный модуль для своего класса Android, вы можете полагаться на автоматическую инъекцию этого класса, чтобы вытащить конфигурацию или экземпляр из графика в этот момент. Поощрите его подход, если проще просто исключить параметры конструктора из вашего модуля, что также может обеспечить лучшую производительность, поскольку они избегают ненужных экземпляров и вызовов виртуальных методов.
Во-первых, кинжал.андроид за 30 секунд: Вместо того, чтобы иметь информацию о его родительской активности или фрагменте, Activity (или Fragment) вызывает AndroidInjection.inject(this)
, который проверяет приложение для HasActivityInjector
(или родительские фрагменты, активность и приложение для HasFragmentInjector
). Идея заключается в том, что вы вносите привязку к создаваемому многосвязью Map<Class, AndroidInjector.Factory>
, где созданные привязки почти всегда являются сборщиками подкомпонентов, которые вы пишете, которые строят объекты-специфические подкомпоненты.
Как вы могли бы сказать из AndroidInjection.inject(this)
и AndroidInjector.Factory.create(T instance)
, у вас не будет большой возможности передать подробные сведения о конкретном конкретном конкретном или фрагменте вашему Builder. Вместо этого идея заключается в том, что ваш субкомпонентный строитель переопределяет реализацию seedInstance
. Как в документах для seedInstance
:
Предоставляет
instance
для использования в графе привязки построенногоAndroidInjector
. По умолчанию это используется как методBindsInstance
, но он может быть переопределен для предоставления любых модулей, которым нужна ссылка на активность.Это должен быть тот же самый экземпляр, который будет передан
inject(Object)
.
Это выглядит примерно так:
@Subcomponent(modules = {OneModule.class, TwoModule.class})
public interface YourActivitySubcomponent extends AndroidInjector<YourActivity> {
// inject(YourActivity) is inherited from AndroidInjector<YourActivity>
@Builder
public abstract class Builder extends AndroidInjector.Builder<YourActivity> {
// Here are your required module builders:
abstract Builder oneModule(OneModule module);
abstract Builder twoModule(TwoModule module);
// By overriding seedInstance, you don't let Dagger provide its
// normal @BindsInstance implementation, but you can supply the
// instance to modules or call your own BindsInstance:
@Override public void seedInstance(YourActivity activity) {
oneModule(new OneModule(activity));
twoModule(new TwoModule(activity.getTwoModuleParameter()));
}
}
}
Предполагается, что вам нужно ждать экземпляра activity
для модулей. Если нет, то у вас также есть возможность вызвать их при привязке подкомпонента:
@Provides @IntoMap @ActivityKey(YourActivity.class)
AndroidInjector.Factory bindInjector(YourActivitySubcomponent.Builder builder) {
return builder
.oneModule(new OneModule(...))
.twoModule(new TwoModule(...));
}
... но если вы можете это сделать, тогда вы можете более легко позаботиться об этих привязках, переопределив эти модули, внедряя конструктор с нулевым аргументом, который может предоставить параметры конструктора модуля, и позволяя кинжалу создавать такие объекты для любых модулей с общедоступными конструкторами с нулевым аргументом.