один объект, если внедрен в 2 подкомпонента в той же пользовательской области, каждый раз, когда создается новый экземпляр этого объекта - PullRequest
0 голосов
/ 11 сентября 2018

один объект, если внедрен в 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 Ответ

0 голосов
/ 11 сентября 2018

Вам нужно будет переместить 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> означает, что ваш экземпляр будет использовать тот же жизненный цикл, что и компонент, также аннотированный этой аннотацией области. Здесь это каждый автоматически сгенерированный подкомпонент. Кроме того, поскольку ваш модуль является неабстрактным классом с открытым конструктором no-arg , Dagger будет автоматически создавать новый экземпляр каждый раз, когда создает компонент, для которого требуется ваш модуль, что означает различный bus для каждый экземпляр деятельности. (Это не может и не будет делать это для модулей, которые являются абстрактными классами или интерфейсами.)


Вы хотите, чтобы ваш объект bus был одним и тем же экземпляром между операциями, что означает, что @CustomScope / @ActivityScope слишком короток: вы хотите, чтобы объект пережил жизненный цикл любой отдельной деятельности. Это означает, что вам нужно либо сохранить экземпляр в другом месте и передать его в каждое действие, либо вам необходимо сохранить экземпляр в самом компоненте приложения. Я бы порекомендовал последнее, потому что это одна из проблем, которые Dagger был создан для решения, и потому что это автоматически сделает шину доступной для вашего приложения: подкомпоненты Dagger наследуют доступ ко всем привязкам в своих родительских компонентах. Это дает код, который вы видите выше. (Обратите внимание, что, выполнив это, вы сохраните экземпляр PublishSubject даже тогда, когда не будет отображаться действие, когда ваше приложение работает в фоновом режиме; если вам нужен один и тот же экземпляр между действиями, это является необходимым следствием, но выберите осторожно, чтобы не использовать слишком много фоновой памяти.)

Одной из альтернатив является то, что вы сами отслеживаете экземпляр bus и вставляете его в каждое действие. Вы могли бы сделать это, если бы ваш модуль принял параметр, но , что довольно сложно сделать с dagger.android (который поддерживает @ContributesAndroidInjector). Вы также можете написать метод @Provides, который делегирует WeakReference, или использовать метод @Singleton, описанный выше, чтобы написать держатель, который временно сохраняет ваш bus между действиями. Тем не менее, поскольку Android в значительной степени контролирует ваши переходы между операциями и жизненным циклом активности, возможно, вы можете сохранить область действия bus в @Singleton, как я делал в приведенном выше коде.

...