Dagger2是一个依赖注入框架,我们经常用到的依赖注入框架还有ButterKnife。说到这里,首先了解一个概念:控制反转。
控制反转(又叫IOC:Inversion Of Control):是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统的所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
说到Dagger2的使用,我们首先了解的是使用Dagger2有什么好处?
Dagger2是用来使代码解耦的,一个类的new代码是非常可能充斥在app的多个类中的,假如该类的构造函数发生变化,那这些涉及到的类都得进行修改。
如果使用Dagger2的Inject注解构造函数,即使构造函数发生较大的变化,我们基本上都不需要修改任何代码。
Dagger2,分为三部分:依赖提供方、依赖需求方、依赖注入容器(即二者之间的桥梁)。
在Dagger2中被@Module注解的类作为提供方、@Component注解的类作为桥梁、@Inject注解的变量作为需求方
这里说一下@Inject
@Inject注解有两个作用:
下面我们就简单说一说,Dagger2的使用步骤:
(1)引入dagger2的库:
// dagger2
implementation 'com.google.dagger:dagger:2.23.1'
annotationProcessor 'com.google.dagger:dagger-compiler:2.23.1'
(2)创建一个类Person,并且在Person类的构造方法上添加上@Inject注解,作为依赖的提供方
public class Person {
private String name;
private int age;
@Inject
public Person(String name,int age){
this.name=name;
this.age=age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
(3) 创建一个Module类:
@Module
public class MainActivityModule {
private String name;
private int age;
public MainActivityModule(String name,int age) {
this.name=name;
this.age=age;
}
@Provides
String provideName(){
return name;
}
@Provides
int provideAge(){
return age;
}
}
注意:这个类的命名以Module结尾,里面针对Person类含有@Inject构造函数的参数,添加provide方法,这些provide方法需要添加@Provides注解,并且命名开头以provide开头。Module类作为依赖提供方,提供构造函数中的参数。Module 其实是一个简单工厂模式,Module 里面的方法都是创建相应类实例的方法。
(4)创建一个Component类,作为依赖提供方和依赖需求方直接的桥梁:
@Component(modules = MainActivityModule.class)
public interface MainActivityComponent {
void inject(MainActivity mainActivity);
}
注意:@Component
一般用来注解接口,负责在@Inject
和@Module
之间建立连接。实例化@Inject
注解的类时,遇到没有构造函数的类依赖,则该依赖由@Module
修饰的类提供。
(5)在Activity中,声明一个Person类型的变量,并被@Inject注解这个变量。
public class MainActivity extends AppCompatActivity {
@Inject
Person person;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerMainActivityComponent.builder()
.mainActivityModule(new MainActivityModule("张三",20))
.build()
.inject(this);
Log.e("===A====",person.getAge()+"====="+person.getName());
person.setName("张三丰");
Log.e("===B====",person.getAge()+"====="+person.getName());
}
}
注意里面还要加上最重要的代码:
DaggerMainActivityComponent.builder()
.mainActivityModule(new MainActivityModule("张三",20))
.build()
.inject(this);
在经过Make Project之后,会生成一个DaggerMainActivityComponent,这个类实现了MainActivityComponent接口:
public final class DaggerMainActivityComponent implements MainActivityComponent {
private final MainActivityModule mainActivityModule;
private DaggerMainActivityComponent(MainActivityModule mainActivityModuleParam) {
this.mainActivityModule = mainActivityModuleParam;
}
public static Builder builder() {
return new Builder();
}
private Person getPerson() {
return new Person(MainActivityModule_ProvideNameFactory.provideName(mainActivityModule), MainActivityModule_ProvideAgeFactory.provideAge(mainActivityModule));}
@Override
public void inject(MainActivity mainActivity) {
injectMainActivity(mainActivity);}
private MainActivity injectMainActivity(MainActivity instance) {
MainActivity_MembersInjector.injectPerson(instance, getPerson());
return instance;
}
public static final class Builder {
private MainActivityModule mainActivityModule;
private Builder() {
}
public Builder mainActivityModule(MainActivityModule mainActivityModule) {
this.mainActivityModule = Preconditions.checkNotNull(mainActivityModule);
return this;
}
public MainActivityComponent build() {
Preconditions.checkBuilderRequirement(mainActivityModule, MainActivityModule.class);
return new DaggerMainActivityComponent(mainActivityModule);
}
}
}
到这里,依赖注入已完成,通过@Inject注解的Person变量就已经有值,可以正常使用了。