如何使用Dagger 2 BindsOptionalOf

Pac*_*co1 3 android dagger-2

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

我知道null使用Dagger 注入值的一种方法,即注释模块中的Provider方法,Component中的依赖项声明和注入站点的参数@Nullable.但是为了更清楚地说明BluetoothAdapter是一个可选的依赖项(应用程序的其余部分也可以在没有BT的情况下工作,并且也应该在模拟器上工作),我想要声明依赖关系,Optional<BluetoothAdapter>如官方文档中所述.

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

@Provides
static BluetoothAdapter providesBluetoothAdapter(MainApplication application) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

以及组件中的相应声明:

BluetoothAdapter bluetoothAdapter();
Run Code Online (Sandbox Code Playgroud)

根据说明,我将注入站点更改为Optional<BluetoothAdapter>,使我的模块抽象化并在模块中添加以下抽象方法:

@BindsOptionalOf abstract BluetoothAdapter optionalBluetoothAdapter();
Run Code Online (Sandbox Code Playgroud)

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

我错过了什么?是否可以通过可选绑定完成我想要做的事情,因为注释的方法@BindsOptionalOf必须是抽象的?

Jef*_*ica 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);
}
Run Code Online (Sandbox Code Playgroud)

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

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