Один объект, если внедрен в 2 подкомпонента в той же пользовательской области, каждый раз, когда создается новый экземпляр этого объекта
Один объект, если его внедрить в 2 подкомпонента в одной и той же пользовательской области, каждый раз, когда создается новый экземпляр этого объекта. Я хочу, чтобы один и тот же экземпляр передавался всем подкомпонентам
это модуль
@CustomScope
@Module
public class EventBusModule {
PublishSubject<Boolean> bus = PublishSubject.create();
@CustomScope
@Provides
public PublishSubject<Boolean> provideRxBus() {
return bus;
}
}
это мои подкомпоненты
@Module
public abstract class ActivityBindingModule {
@CustomScope
@ContributesAndroidInjector(modules = {HomeActivityModule.class,
EwayBillFragmentProvider.class, EventBusModule.class})
abstract HomeActivity mainActivity();
@CustomScope
@ContributesAndroidInjector(modules =
{EwayBillDetailActivityModule.class, EventBusModule.class})
abstract EwayBillDetailActivity ewayBillDetailActivity();
}
Эти подкомпоненты написаны внутри ActivityBindingModule, который добавлен в мой компонент приложения. Теперь мне нужен один и тот же экземпляр моего объекта PublishSubject в обоих подкомпонентах, я новичок в кинжале и хочу знать, что я делаю не так?
1 ответ
Вам нужно будет переместить bus
в область применения, что обычно означает аннотирование @Singleton
(если вы так аннотировали свой компонент верхнего уровня, в который установлен ActivityBindingModule). Вам также нужно будет переместить ваш метод в модуль, установленный на этом компоненте, который также может быть ActivityBindingModule.
@Module
public abstract class ActivityBindingModule {
@Singleton
@Provides
public PublishSubject<Boolean> provideRxBus() {
// Dagger stores the instance in your Application component, so you don't have to.
return PublishSubject.create();
}
/* ... your @ContributesAndroidInjector Activity bindings remain here ... */
}
Сначала объяснение того, что вы видите: @ContributesAndroidInjector
создает подкомпонент для каждого аннотируемого объекта, помеченный аннотациями области действия и модулями, которые вы надеваете @ContributesAndroidInjector
метод и аннотации, так что ваш вызов AndroidInjection.inject(this)
в onCreate
создает новый экземпляр этого подкомпонента и использует его для внедрения экземпляра Activity.
Ваш @CustomScope
(который может быть лучше назван как @ActivityScope
здесь) на @Provides PublishSubject<Boolean>
Метод означает, что ваш экземпляр будет использовать тот же жизненный цикл, что и компонент, также аннотированный этой аннотацией области действия. Здесь каждый автоматически генерируемый подкомпонент. Кроме того, поскольку ваш модуль является неабстрактным классом с открытым конструктором без аргументов, Dagger автоматически создает новый экземпляр каждый раз, когда создает компонент, для которого требуется ваш модуль, что означает bus
для каждого экземпляра Activity. (Это не может и не будет делать это для модулей, которые являются абстрактными классами или интерфейсами.)
Вы хотите, чтобы ваш bus
объект должен быть одним и тем же экземпляром между действиями, что означает, что @CustomScope
/ @ActivityScope
слишком короток: вы хотите, чтобы объект пережил жизненный цикл любого отдельного действия. Это означает, что вам нужно либо сохранить экземпляр в другом месте и передать его в каждое действие, либо вам необходимо сохранить экземпляр в самом компоненте приложения. Я бы порекомендовал последнее, потому что это одна из проблем, которые Dagger был создан для решения, и потому что это автоматически сделает шину доступной для вашего приложения: подкомпоненты Dagger наследуют доступ ко всем привязкам в своих родительских компонентах. Это дает код, который вы видите выше. (Обратите внимание, что, выполнив это, вы сохраните экземпляр PublishSubject даже в том случае, если не будет отображаться действие, когда ваше приложение работает в фоновом режиме; если вы хотите, чтобы один и тот же экземпляр был между действиями, это необходимое следствие, но выберите это тщательно, чтобы избежать слишком большого использования фоновой памяти.)
Одним из вариантов является то, что вы отслеживаете bus
например, и вставьте его в каждое действие. Вы можете сделать это, если ваш модуль получит параметр, но это довольно сложно сделать с dagger.android (который @ContributesAndroidInjector
). Вы также можете написать @Provides
метод, который делегирует WeakReference, или использовать @Singleton
Техника выше, чтобы написать держатель, который временно хранит ваши bus
между мероприятиями. Однако, поскольку Android в значительной степени контролирует ваши переходы между операциями и жизненным циклом активности, возможно, лучше всего сохранить bus
в @Singleton
сфера, как я сделал в коде выше.