Dagger2——Optional bindings

·  阅读 362

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类。

测试1:

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注解

测试2:

此时会编译错误:[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();
    }
//***
}
复制代码

测试3:

此时仍会编译错误:@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();
}
复制代码

测试4:

这种情况下编译成功,但是Optional.isPresent()返回false,因为新的Module类提供的实例时BMWWheel类型的,并非IWheel类型,所以依赖关系仍然找不到。

修改新的Module类提供IWheel的实例:

@Module
public class BMWWheelModule {
    @Provides
    IWheel provideWheel() {
        return new BMWWheel();
    }
}
复制代码

测试5:

这时运行后,Optional.isPresent()返回true,因为新的Module类能够提供IWheel类型的依赖,所以能够把一个IWheel类型的实例注入到Optional的对象中。

分类:
Android
标签:
分类:
Android
标签: