如果在同一自定义范围内将一个对象注入到 2 个子组件中,则每次创建该对象的新实例时

one object if injected into 2 subcomponents under same custom scope, every time new instance is created of that object

如果在同一自定义范围内将一个对象注入到 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 对象的相同实例,我对 dagger 还很陌生,我想知道我做错了什么?

您需要将 bus 移动到应用程序范围,这通常意味着用 @Singleton 对其进行注释(如果这就是您注释 [=49= 的顶级组件的方式) ]BindingModule 安装到)。您还需要将您的方法移动到安装在该组件上的模块中,也可能是 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 方法和注释,以便您在 onCreate 中调用 AndroidInjection.inject(this) 创建该子组件的新实例并使用它注入 Activity 实例。

你的@CustomScope(在这里命名为@ActivityScope更好)在@Provides PublishSubject<Boolean>方法上意味着你的实例将与同样被注释的组件共享相同的生命周期使用该范围注释。在这里,这是每个自动生成的子组件。此外,由于您的模块是 非抽象 class 且具有 public 无参数构造函数 ,Dagger 会在每次创建组件时自动创建一个新实例需要您的模块,这意味着每个 Activity 实例都有不同的 bus。 (对于抽象 classes 或接口的模块,它不能也不会这样做。)


您希望您的 bus 对象在 Activity 之间是同一个实例,这意味着 @CustomScope/@ActivityScope 太短了:您希望该对象比任何单个 Activity的生命周期。这意味着您需要将实例存储在别处并将其传递给每个 Activity,或者您需要将实例存储在您的 Application 组件本身中。我推荐后者,因为这是创建 Dagger 来解决的问题之一,并且因为这会自动使总线在您的应用程序中可用:Dagger 子组件继承对其父组件中所有绑定的访问权。这给出了您在上面看到的代码。 (请注意,通过这样做,即使没有 Activity 显示,当您的应用程序在后台 运行 时,您也会保留 PublishSubject 的实例;如果您想要在 Activity 之间使用相同的实例,这是必然的结果,但请谨慎选择以避免过多的后台内存使用。)

一种替代方法是您自己跟踪 bus 实例,并将其插入到每个 Activity 中。你可以通过让你的模块接受一个参数来做到这一点,但是 (它支持 @ContributesAndroidInjector)。您还可以编写一个委托给 WeakReference 的 @Provides 方法,或者使用上面的 @Singleton 技术编写一个容器,在 Activity 之间临时存储您的 bus。但是,因为 Android 对 Activity 和 Activity 生命周期之间的转换进行了大量控制,所以最好将 bus 保持在 @Singleton 范围内正如我在上面的代码中所做的那样。