我正在使用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();
注释的方法必须是抽象的?
答案 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来反映是否存在:您自己控制它。