java中提供了Optional用来解决空指针异常,它包裹的对象可能是空,使用时需要调用Optional.isPresent()方法判断内部的实例是否为空。Dagger2提供了@BindsOptionalOf注解用来注入Optional类型的变量。
所以如果T类型的依赖能够在Component中找到,那么Optional包裹的对象非空,如果找不到依赖关系,那么就会返回空。
public class BMW {
@Inject
public BMW() {
super();
@Inject
Optional<IWheel> wheel;
BMW中有一个Optional类型的变量wheel。
@Module
abstract class WheelModel {
@BindsOptionalOf abstract IWheel provideWheel();
在WheelModel中给providWheel()方法增加了@BindsOptionalOf注解,那么Dagger2就会在Component中寻找是否存在能够提供IWheel实例的依赖关系。
@Component(modules = {WheelModel.class})
public interface CarComponent {
BMW makeBmw();
在Component中依赖了WheelModel这个Module类。
public class CarMain {
public static void main(String[] args) {
CarComponent component = DaggerCarComponent.create();
BMW bmw = component.makeBmw();
System.out.println(bmw.wheel.isPresent());
显然,此时会打印false,因为在Component中并没有谁能够提供IWheel实例。
此时将WheelModel中的方法返回的类型修改为具体的类型BMWWheel,会发生什么:
@Module
abstract class WheelModel {
@BindsOptionalOf abstract BMWWheel provideWheel();
其中的BMWWheel:
public class BMWWheel implements IWheel {
public BMWWheel() {
super();
//***
注意,目前并没有在BMWWheel的构造函数上增加@Inject注解
此时会编译错误:[Dagger/MissingBinding] java.util.Optional<com.hero.IWheel> cannot be provided without an @Inject constructor or an @Provides-annotated method.
说明,Optional需要对象依赖关系中有该类型的构造函数被@Inject注解,或者Module类中有被@Provides注解的提供该类型实例的方法,否则肯定找不到依赖关系。
给BMWWheel增加@Inject注解:
public class BMWWheel implements IWheel {
@Inject
public BMWWheel() {
super();
//***
此时仍会编译错误:@BindsOptionalOf methods cannot return unqualified types that have an @Inject-annotated constructor because those are always present。
说明:如果@BindsOptionalOf注解的方法返回的是一个具体类型,如果这个类型的构造函数有@Inject,那么每次都能注入具体的实例,也就是说,这种场景下不需要使用@BindsOptionalOf
那么应该怎么办呢?
提供另一个Module类,它能够提供所需的依赖
@Module
public class BMWWheelModule {
@Provides
BMWWheel provideWheel() {
return new BMWWheel();
新建一个BMWWheelModule提供BMWWheel实例。
@Module
abstract class WheelModel {
@BindsOptionalOf abstract IWheel provideWheel();
并且在Component中依赖这个新的Module
@Component(modules = {WheelModel.class, BMWWheelModule.class})
public interface CarComponent {
BMW makeBmw();
这种情况下编译成功,但是Optional.isPresent()返回false,因为新的Module类提供的实例时BMWWheel类型的,并非IWheel类型,所以依赖关系仍然找不到。
修改新的Module类提供IWheel的实例:
@Module
public class BMWWheelModule {
@Provides
IWheel provideWheel() {
return new BMWWheel();
这时运行后,Optional.isPresent()返回true,因为新的Module类能够提供IWheel类型的依赖,所以能够把一个IWheel类型的实例注入到Optional的对象中。