如何使用Dagger 2 BindsOptionalOf

时间:2017-03-24 11:50:51

标签: android dagger-2

我正在使用Dagger 2构建一个Android应用程序,如果它可用,它支持蓝牙。我想用Dagger注入BluetoothAdapter依赖。

我知道使用Dagger注入null值的一种方法,即注释Module中的Provider方法,Component中的依赖项声明和注入站点上@Nullable的参数。但为了更清楚地说明BluetoothAdapter是一个可选依赖项(应用程序的其余部分也可以在没有BT的情况下工作,也应该在模拟器上工作),我想将依赖项声明为{{1如in the official docs所述。

我的模块中有一个Provider方法:

Optional<BluetoothAdapter>

以及组件中的相应声明:

@Provides
static BluetoothAdapter providesBluetoothAdapter(MainApplication application) {
    ...
}

根据说明,我将注射网站更改为BluetoothAdapter bluetoothAdapter(); ,使我的模块成为抽象,并在模块中添加了以下抽象方法:

Optional<BluetoothAdapter>

但是,在模拟器上运行时,它仍会失败并出现@BindsOptionalOf abstract BluetoothAdapter optionalBluetoothAdapter(); 异常。 当我想到这可能是我误解了java.lang.NullPointerException: Cannot return null from a non-@Nullable @Provides method的目的并从我的组件中删除了@BindsOptionalOf声明,看它是否取决于是否在组件中声明了依赖关系。仍然无法工作。

我错过了什么?是否有可能通过可选绑定完成我想要做的事情,因为用BluetoothAdapter bluetoothAdapter();注释的方法必须是抽象的?

1 个答案:

答案 0 :(得分:10)

你并没有完全按照它的意思使用@BindsOptionalOf。 @BindsOptionalOf最适合在编译时可能存在或不存在的绑定,因此最适合可重用模块

让我们说你正在构建一个可重用的库:

@Module public abstract class BluetoothAdapterModule {
  @Provides
  static BluetoothAdapter providesBluetoothAdapter(MainApplication application) {
    ...
  }
}

@Module public interface FooModule {
  // This consumes BluetoothAdapter when it happens to be present.
  @BindsOptionalOf BluetoothAdapter bindOptionalBluetoothAdapter();

  @Binds Bar bindBar(Foo foo);
}

这里,当FooModule和BluetoothAdapterModule绑定到同一个Component时,会有一个绑定BluetoothAdapter,因此可以注入Optional<BluetoothAdapter>get将返回BluetoothAdapter。在您没有包含BluetoothAdapterModule的单独组件中,BluetoothAdapter没有绑定。如果你直接从Foo依赖BluetoothAdapter,包括@Nullable BluetoothAdapter,你的编译就会失败。但是,对于@BindsOptionalOf,您可以依赖Optional<BluetoothAdapter>的注入,当包含BluetoothAdapterModule时它会出现,而当它被排除时则不存在。

要在运行时反映蓝牙的存在与否,您需要使用@Nullable或您编写的单独注射BluetoothAdapterHolder。您还可以显式绑定Optional<BluetoothAdapter>,并使用您期望的在线或缺席特征明确创建它;此时,您不会使用@BindsOptionalOf,因为您并不依赖Dagger来反映是否存在:您自己控制它。

相关问题