@Module
@Module注解在类或接口上,表明该类或接口用于提供相关依赖。该类或接口中使用的注解有@Provides,@Binds,@IntoSet,@IntoMap。
@Provides
最常用,注解在非抽象方法上,返回值是程序中需要用到的依赖。
代码:
@Module
public class ProvidesModule {
/* 形式一:自己构建Windable实例
@Provides
public Windable provideWindable(){
return new WindableImpl();
}*/
/**
* 形式二:让Dagger构建Windable实例,此时需要在WindableImpl构造函数上打上@Inject注解
*/
@Provides
public Windable provideWindable(WindableImpl windable){
return windable;
}
}
针对@Provides注解,编译期Dagger会生成格式为:
Module类名_方法名Factory 的类并且实现了Factory接口。
针对本例生成的类就是ProvidesModule_ProvideWindableFactory
public final class ProvidesModule_ProvideWindableFactory implements Factory {
private final ProvidesModule module;
private final Provider windableProvider;
public ProvidesModule_ProvideWindableFactory(
ProvidesModule module, Provider windableProvider) {
this.module = module;
this.windableProvider = windableProvider;
}
@Override
public Windable get() {
return provideInstance(module, windableProvider);
}
public static Windable provideInstance(
ProvidesModule module, Provider windableProvider) {
return proxyProvideWindable(module, windableProvider.get());
}
public static ProvidesModule_ProvideWindableFactory create(
ProvidesModule module, Provider windableProvider) {
return new ProvidesModule_ProvideWindableFactory(module, windableProvider);
}
public static Windable proxyProvideWindable(ProvidesModule instance, WindableImpl windable) {
return Preconditions.checkNotNull(
instance.provideWindable(windable),
"Cannot return null from a non-@Nullable @Provides method");
}
}
生成的类的格式也是相对固定的。
一个静态create方法,返回值是该Factory类实例。
一个构造函数。
一个get方法,来自Factory接口,用于返回依赖。
注意:每个用@Provides注解的方法都会生成相应的Factory类。
@Binds
也是用于提供依赖,跟@Provides注解功能一样。不同的是@Binds注解于抽象方法上,返回值是依赖的接口或父类型或本类型,方法只有一个参数,就是返回值的实现者。既然@Binds注解于抽象方法,那么@Module注解的类就必须是接口或抽象类了。
代码:
@Module
public interface BindsModule {
/**
* 注解于抽象方法,只能有一个参数
* @param windable
* @return
*/
@Binds
Windable provideWindable(WindableImpl windable);
}
@IntoSet
@IntoSet需要联合@Provides一起使用,@IntoSet注解的方法表示方法返回值放入一个Set集合中,多个@IntoSet注解的方法,若方法返回值类型一致,则会放入同一个Set集合中。
@Module
public class IntoSetModule {
@Provides
@IntoSet
public String provideA(){
return "A";
}
@Provides
@IntoSet
public String provideB(){
return "B";
}
}
public class IntoSetDemo {
@Inject
Set letters;
IntoSetDemo(){
}
public static void main(String[] args){
IntoSetDemo demo=new IntoSetDemo();
DaggerIntoSetComponent.create().inject(demo);
for (String letter:demo.letters){
System.out.print(letter);
}
}
}
Module类中的provideA和provideB方法的返回值被放入同一个Set集合中,所以该例的输出结果是AB。
@IntoMap
@IntoMap需要联合@IntKey,@StringKey或者自定义的@MapKey以及@Provides一起使用。如果map的key为int类型,则用@IntKey,为String类型,则用@StringKey,如果为其他类型,则需要自定义注解,并在自定义注解上打上@MapKey。
@Module
public class IntoMapModule {
@Provides
@IntoMap
@IntKey(1)
public String provideNameA(){
return "nameA";
}
@Provides
@IntoMap
@IntKey(2)
public String provideNameB(){
return "nameB";
}
}
public class IntoMapDemo {
@Inject
Map map;
IntoMapDemo(){
}
public static void main(String[] args){
IntoMapDemo demo=new IntoMapDemo();
DaggerIntoMapComponent.create().inject(demo);
System.out.println("key=1,value="+demo.map.get(1));
System.out.println("key=2,value="+demo.map.get(2));
}
}
IntoMapModule类中的provideNameA方法指定了key为1,value为nameA,provideNameB方法指定了key为2,value为nameB,他们被放入同一个map中。所以程序的输出结果是
key=1,value=nameA
key=2,value=nameB
@Component
@Component 注解的类(一般是接口或抽象类)用于为具体的类注入依赖。
@Component 注解有两个属性:
一个是modules属性,关联相关的Module
一个是dependencies属性,关联子Component
一般需要提供一个inject()方法,参数是需要注入的类;当然也可以定义一个直接获取依赖的方法,比如Activity类中需要注入一个Presenter对象,可以直接在Component接口中定义一个presenter方法,在Activity类中需要使用Presenter时使用component.presenter()就可以了。
a.inject法:
@Component(modules = MyModule.class)
public interface MyComponent {
/**
* 定义一个inject方法,注入ComponentDemo需要的依赖
* @param componentDemo
*/
void inject(ComponentDemo componentDemo);
}
public class ComponentDemo {
@Inject
MyService myService;
ComponentDemo(){
}
public static void main(String args[]){
ComponentDemo componentDemo=new ComponentDemo();
//将MyService注入
DaggerMyComponent.create().inject(componentDemo);
componentDemo.myService.serve();
}
}
MyModule提供了MyService实例。
b.Component提供一个myService()方法
@Component(modules = MyModule.class)
public interface MyComponent {
//定义一个方法提供依赖
MyService myService();
}
public class ComponentDemo {
MyService myService;
ComponentDemo(){
}
public static void main(String args[]){
ComponentDemo componentDemo=new ComponentDemo();
componentDemo.myService=DaggerMyComponent
.create()
.myService();
componentDemo.myService.serve();
}
}
@Component注解在编译期生成的源码格式:
1,实现@Component注解的接口
2,静态内部类Builder,含有用于设置@Component注解中modules的方法
3,生成的Component类名为@Component注解的接口的简单名称加前缀Dagger。
4,一个接收builder的构造函数,保存相关的module。
5,实现@Component注解的接口中定义的方法
@Generated(
value = "dagger.internal.codegen.ComponentProcessor",
comments = "https://google.github.io/dagger"
)
public final class DaggerMyComponent implements MyComponent {
private MyModule myModule;
private DaggerMyComponent(Builder builder) {
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
public static MyComponent create() {
return new Builder().build();
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.myModule = builder.myModule;
}
@Override
public MyService myService() {
return MyModule_ProvideMyServiceFactory.proxyProvideMyService(myModule);
}
public static final class Builder {
private MyModule myModule;
private Builder() {}
public MyComponent build() {
if (myModule == null) {
this.myModule = new MyModule();
}
return new DaggerMyComponent(this);
}
public Builder myModule(MyModule myModule) {
this.myModule = Preconditions.checkNotNull(myModule);
return this;
}
}
}
@Inject
当@Inject标注在构造器时,说明该类的实例交由Dagger生成,Dagger会在编译期间生成一个XXX_Factory类。
当@Inject标注在字段上时,Dagger会在编译期生成一个XXX_MembersInjector类。
public class MapKeyDemo {
@Inject
Map map;
private String param;
@Inject
public MapKeyDemo(String param){
this.param=param;
}
public static void main(String [] args){
MapKeyComponent mapKeyComponent=DaggerMapKeyComponent.create();
MapKeyDemo mapKeyDemo=mapKeyComponent.mapKeyDemo();
mapKeyComponent.inject(mapKeyDemo);
}
}
生成的类
@Generated(
value = "dagger.internal.codegen.ComponentProcessor",
comments = "https://google.github.io/dagger"
)
public final class MapKeyDemo_Factory implements Factory {
private final Provider paramProvider;
private final Provider
@Subcomponent
Subcomponent可以使用Component提供的依赖,因此一些公共的组件信息可以由Component提供。
Component和Module
@Module
public class MyModule {
@Provides
public MyService provideMyService(){
return new MyService();
}
}
@Component(modules = MyModule.class)
public interface MyComponent {
//添加Subcomponent
MySubComponent plus(MySubModule mySubModule);
}
Subcomponent和它的Module
@Module
public class MySubModule {
}
@Subcomponent(modules = MySubModule.class)
public interface MySubComponent {
void inject(SubcomponentDemo demo);
}
注意MyService是在MyModule中提供的而不是MySubModule提供的
使用
public class SubcomponentDemo {
@Inject
MyService myService;
SubcomponentDemo() {
}
public static void main(String[] args) {
SubcomponentDemo demo = new SubcomponentDemo();
DaggerMyComponent
.builder()
.build()
.plus(new MySubModule())//向Component中添加SubComponent,并返回SubComponent
.inject(demo);//注入依赖
demo.myService.serve();//成功注入,说明subcomponent可以使用component提供依赖
}
}
看一下生成的Component源码
public final class DaggerMyComponent implements MyComponent {
private MyModule myModule;
private DaggerMyComponent(Builder builder) {
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
public static MyComponent create() {
return new Builder().build();
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.myModule = builder.myModule;
}
@Override
public MySubComponent plus(MySubModule mySubModule) {
return new MySubComponentImpl(mySubModule);
}
public static final class Builder {
private MyModule myModule;
private Builder() {}
public MyComponent build() {
if (myModule == null) {
this.myModule = new MyModule();
}
return new DaggerMyComponent(this);
}
public Builder myModule(MyModule myModule) {
this.myModule = Preconditions.checkNotNull(myModule);
return this;
}
}
/**
* Subcomponent以内部类形式存在于Component类中
*/
private final class MySubComponentImpl implements MySubComponent {
private MySubComponentImpl(MySubModule mySubModule) {}
@Override
public void inject(SubcomponentDemo demo) {
injectSubcomponentDemo(demo);
}
@CanIgnoreReturnValue
private SubcomponentDemo injectSubcomponentDemo(SubcomponentDemo instance) {
SubcomponentDemo_MembersInjector.injectMyService(
instance,
MyModule_ProvideMyServiceFactory.proxyProvideMyService(DaggerMyComponent.this.myModule));
return instance;
}
}
}
可以看到 Subcomponent以内部类形式存在于Component类中