Dagger2进阶-@Qualifier、@Lazy

Qualifier

当同一个对象有多种注入方式,Dagger2怎么知道使用哪种方式注入呢?
因此需要用到@Qualifier表识的注解来限定,而@Name也是一种@Qualifier注解。因此提供的地方使用@Name方式如下:

@Module
public class SubModule {

    @Named("aaa")
    @ActivitySingleton
    @Provides
    public Logger providerLogger(Retrofit retrofit) {
        System.out.println("aaaa");
        return new Logger(retrofit);
    }

    @Named("bbb")
    @ActivitySingleton
    @Provides
    public Logger providerLoggerB(Retrofit retrofit) {
        System.out.println("bbbb");
        return new Logger(retrofit);
    }

}

使用不同的方式注入的代码如下:

    @Inject
    @Named("aaa")
    Logger logger;
    @Inject
    @Named("bbb")
    Logger logger2;

在使用@Named("")的地方也可以换成自定义Qualifier注解
例如

@Qualifier
@Documented
@Retention(RUNTIME)
public @interface AAAA {

}
//BBB省略...

则Module中代码如下:

@Module
public class SubModule {

    @AAA
    @ActivitySingleton
    @Provides
    public Logger providerLogger(Retrofit retrofit) {
        System.out.println("aaaa");
        return new Logger(retrofit);
    }

    @BBB
    @ActivitySingleton
    @Provides
    public Logger providerLoggerB(Retrofit retrofit) {
        System.out.println("bbbb");
        return new Logger(retrofit);
    }

}

使用的地方注解也修改成@AAA、@BBB即可。

Lazy

Dagger2可以使用懒加载,当Lazy 等同于注入T,只是生成T的时间在调用lazy.get()时,且多次调用get方法,返回的是同一个对象T。例如延时获取Logger的代码如下:

public class Street {

    @Inject
    @AAA
    Logger logger;
    @Inject
    @BBB
    Lazy logger2;

    public Street() {

    }

    public void byCoffee() {
        AppComponent netComponent = AppManager.getAppComponent();
        CoffeeShopComponent coffeeShopComponent = netComponent.getCoffeeShopComponentBuilder().build();
        coffeeShopComponent.inject(this);
        logger.log("inject success");
        logger2.get().log("inject success 2");
    }

}

lazy是一种对注入对象的包装,还有一种对注入对象的包装是Provider,看一下CoffeeShopComponent的实现,可以发现里面就用到了Provider,代码如下

private final class CoffeeShopComponentImpl implements CoffeeShopComponent {
    private Provider providerLoggerProvider;

    private Provider providerLoggerBProvider;

    private CoffeeShopComponentImpl(SubModule subModuleParam) {

      initialize(subModuleParam);
    }

    @SuppressWarnings("unchecked")
    private void initialize(final SubModule subModuleParam) {
      this.providerLoggerProvider = DoubleCheck.provider(SubModule_ProviderLoggerFactory.create(subModuleParam, DaggerAppComponent.this.providerRetrofitProvider));
      this.providerLoggerBProvider = DoubleCheck.provider(SubModule_ProviderLoggerBFactory.create(subModuleParam, DaggerAppComponent.this.providerRetrofitProvider));
    }

    @Override
    public void inject(Street street) {
      injectStreet(street);}

    private Street injectStreet(Street instance) {
      Street_MembersInjector.injectLogger(instance, providerLoggerProvider.get());
      Street_MembersInjector.injectLogger2(instance, DoubleCheck.lazy(providerLoggerBProvider));
      return instance;
    }
  }

Provider.get() 方法会强制调用生成T,具体如何生成有Module中定义决定。多次调用等同于定义了多个注入对象,因此多次调用是否会返回相同的对象,等同于多个变量是否是相等的,也就是取决于该注入对象是否在Component实例内是单例的。Provider使用方式如下:

public class Street {

    @Inject
    @AAA
    Logger logger;
    @Inject
    @BBB
    Provider logger2;

    public Street() {

    }

    public void byCoffee() {
        AppComponent netComponent = AppManager.getAppComponent();
        CoffeeShopComponent coffeeShopComponent = netComponent.getCoffeeShopComponentBuilder().build();
        coffeeShopComponent.inject(this);
        logger.log("inject success,get1:"+logger2.get().hashCode()+" ge2:"+logger2.get().hashCode());
    }

}

logger2.get()多次调用是否返回同一对象取决于Module中限定@BBB的提供方式是否是单例的。
单例:

    @BBB
    @ActivitySingleton
    @Provides
    public Logger providerLoggerB(Retrofit retrofit) {
        System.out.println("bbbb");
        return new Logger(retrofit);
    }

非单例:

    @BBB
    //@ActivitySingleton
    @Provides
    public Logger providerLoggerB(Retrofit retrofit) {
        System.out.println("bbbb");
        return new Logger(retrofit);
    }

你可能感兴趣的:(Dagger2进阶-@Qualifier、@Lazy)