欢迎大家下载我个人开发的app安琪花园
主要带着如下几个问题对dagger进行了解
- 面向对象的六大原则是什么
- dagger使用场景
- dagger原理
面向对象的六大原则
- 依赖倒置原则
- 迪米特原则
- 单一职责原则
- 接口隔离原则
- 里氏替换原则
- 开闭原则
而Dagger 是属于依赖注入, 对象的初始化不放在类里面初始化,
而是通过注入的方式,可以说是属于面向对象里面的开闭原则。
而Dagger能解决解耦的问题。当对Model修改的时候 只需要修改一个地址即可
通过一张效果图来看一下Dagger的工作原理
image.png上图的只是说明了Dagger的一个原理。
比如:Activity里面有一个Student的属性。
而这个属性的初始化不是直接放在Activity里面初始化的
而是委托了Dagger来初始化的。
而Dagger 具体是如何对属性初始化的呢
image.png
上面这个效果图对Dagger的工作流程体现得淋漓尽致
可以简单理解为:
Student对象通过包裹后转成Module经Component运送到Activity
从而完成了初始化的工作。
为什么要用Dagger来初始化呢
起初是不是觉得Dagger对对象的初始化反而变得复杂了。
对于只有一个页面来说确实复杂了。直接在Activity里面初始化多方便呢
但是反过来说, 如果有成千上万个Activity里面都有对Student初始化呢
那就在所有的Activity里面把对象给New出来,
但是如果有一天Student的构造方法改变了,
那是不是所有的Activity里面都得去调整。
是不是觉得很麻烦呢?
这个时候Dagger就能派上用场了。 只需要修改一次就能达到事半功倍的效果。
Dagger具体是怎么用的呢?
首先在build.gradle里面添加依赖
implementation "com.google.dagger:dagger:2.4"
annotationProcessor 'com.google.dagger:dagger-compiler:2.4'
假若我项目里面有多个Activity里面需要用到Student的实体类
public class Student {
String name = "liu";
Student(int value) {
}
}
Activity 要委托Dagger来初始化对象, 肯定需要提供一个获取对象的方法:
@Module
public class StudentModule {
@Provides
public Student getStudent() {
return new Student(99);
}
}
补充一点
在Dagger的使用必须要创建一个Module, 也就是上面的一个类, 其扮演了上面图片上面的Module的角色, 这个类必须要添加Module注解, 这样Dagger里面的注解处理器才能找到StudentModule
编译后经过注解处理器后 会生成如下的类
@Generated(
value = "dagger.internal.codegen.ComponentProcessor",
comments = "https://google.github.io/dagger"
)
public final class StudentModule_GetStudentFactory implements Factory<Student> {
private final StudentModule module;
public StudentModule_GetStudentFactory(StudentModule module) {
assert module != null;
this.module = module;
}
@Override
public Student get() {
return Preconditions.checkNotNull(
module.getStudent(), "Cannot return null from a non-@Nullable @Provides method");
}
public static Factory<Student> create(StudentModule module) {
return new StudentModule_GetStudentFactory(module);
}
}
该类其实就是通过工厂模式来生产Student类, 通过create方法得到 StudentModule_GetStudentFactory实例, 然后调用get方法即可得到Student实例了
既然Activity里面的Student属性的初始化是委托给Dagger初始化的,
那么肯定需要将当前Activity注入到Dagger中,
首先需要定义一个接口, 并添加注解Component
这个接口就 扮演了上面 图片中的Component角色
@Component(modules = StudentModule.class) // 快递员拿到了包裹
public interface StudentComponent {
// 送到收货地址 --- 注入到Activity
void injectMainActivity(MainActivity mainActivity); // 不支持多态功能的
void injectMainActivity(MainActivity2 mainActivity);
void injectMainActivity(MainActivity3 mainActivity);
void injectMainActivity(MainActivity4 mainActivity);
}
编译后经过注解处理器后 会生成如下的类
@Generated(
value = "dagger.internal.codegen.ComponentProcessor",
comments = "https://google.github.io/dagger"
)
public final class DaggerStudentComponent implements StudentComponent {
private Provider<Student> getStudentProvider;
private MembersInjector<MainActivity> mainActivityMembersInjector;
private MembersInjector<MainActivity2> mainActivity2MembersInjector;
private MembersInjector<MainActivity3> mainActivity3MembersInjector;
private MembersInjector<MainActivity4> mainActivity4MembersInjector;
private DaggerStudentComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
public static StudentComponent create() {
return builder().build();
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.getStudentProvider = StudentModule_GetStudentFactory.create(builder.studentModule);
this.mainActivityMembersInjector = MainActivity_MembersInjector.create(getStudentProvider);
this.mainActivity2MembersInjector = MainActivity2_MembersInjector.create(getStudentProvider);
this.mainActivity3MembersInjector = MainActivity3_MembersInjector.create(getStudentProvider);
this.mainActivity4MembersInjector = MainActivity4_MembersInjector.create(getStudentProvider);
}
@Override
public void injectMainActivity(MainActivity mainActivity) {
mainActivityMembersInjector.injectMembers(mainActivity);
}
@Override
public void injectMainActivity(MainActivity2 mainActivity) {
mainActivity2MembersInjector.injectMembers(mainActivity);
}
@Override
public void injectMainActivity(MainActivity3 mainActivity) {
mainActivity3MembersInjector.injectMembers(mainActivity);
}
@Override
public void injectMainActivity(MainActivity4 mainActivity) {
mainActivity4MembersInjector.injectMembers(mainActivity);
}
public static final class Builder {
private StudentModule studentModule;
private Builder() {}
public StudentComponent build() {
if (studentModule == null) {
this.studentModule = new StudentModule();
}
return new DaggerStudentComponent(this);
}
public Builder studentModule(StudentModule studentModule) {
this.studentModule = Preconditions.checkNotNull(studentModule);
return this;
}
}
}
通过如下的方法将当前的Activity委托给Dagger,
只需要在Activity的onCreate方法里面调用如下的一句代码
这样Activity里面的student属性就已经赋值了
DaggerStudentComponent.create().injectMainActivity(this);
Dagger是怎么知道获取的Student实例赋值给Activity的哪一个属性呢
这就需要添加Inject注解
@Inject
Student student;
编译后经过注解处理器后 会生成如下的类
@Generated(
value = "dagger.internal.codegen.ComponentProcessor",
comments = "https://google.github.io/dagger"
)
public final class MainActivity2_MembersInjector implements MembersInjector<MainActivity2> {
private final Provider<Student> studentProvider;
public MainActivity2_MembersInjector(Provider<Student> studentProvider) {
assert studentProvider != null;
this.studentProvider = studentProvider;
}
public static MembersInjector<MainActivity2> create(Provider<Student> studentProvider) {
return new MainActivity2_MembersInjector(studentProvider);
}
@Override
public void injectMembers(MainActivity2 instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
instance.student = studentProvider.get();
}
public static void injectStudent(MainActivity2 instance, Provider<Student> studentProvider) {
instance.student = studentProvider.get();
}
}
说到这里Dagger的接入到这里就已经结束了
接下来剖析一下,这句代码是如何就对student初始化的DaggerStudentComponent.create().injectMainActivity(this);
其可分为两步:
第一步: 调用create方法
第二步: 调用injectMainActivit方法
第一步:
public static StudentComponent create() {
return builder().build();
}
builder()方法得到的是Builder实例, 调用build()方法会初始化一个StudentModule
然后得到DaggerStudentComponent实例
public StudentComponent build() {
if (studentModule == null) {
this.studentModule = new StudentModule();
}
return new DaggerStudentComponent(this);
}
而DaggerStudentComponent的构造方法里面做了一些初始化操作, 调用 如下的方法
private void initialize(final Builder builder) {
this.getStudentProvider = StudentModule_GetStudentFactory.create(builder.studentModule);
this.mainActivityMembersInjector = MainActivity_MembersInjector.create(getStudentProvider);
}
首先会得到getStudentProvider实例, 其实就是注解处理器生成的
StudentModule_GetStudentFactory类的实例, 这个类的作用就是生产Student实例
然后对Inject注解生成的类调用create方法,后加值赋值给mainActivityMembersInjector
第二步
@Override
public void injectMainActivity(MainActivity mainActivity) {
mainActivityMembersInjector.injectMembers(mainActivity);
}
其主要看injectMembers方法体
public void injectMembers(MainActivity instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
instance.student = studentProvider.get();
}
在这个方法里面就已经看到了student的初始化了
整个项目里面对student的初始化就已经说明白了。
思考
**
上面的代码里面只是通过Dagger来对一个Student初始化
那如果,我要通过Dagger来对一个Map, 或者Set初始化
那应该如何实现呢
**
将目光聚集到StudentModule类上面, 会发现getStudent方法上面添加了Provides注解
@Documented @Target(METHOD) @Retention(RUNTIME)
public @interface Provides {
enum Type {
UNIQUE,
SET,
SET_VALUES,
@Beta
MAP;
}
Type type() default Type.UNIQUE;
}
这里面定义了一个枚举类型, 而上面的代码只是测了UNIQUE这种类型,
对于其它的类型,大家可以举一反三,亲自试试。
其它文章:
android 面试题
android 自定义阴影 ShadowView
android EventBus源码阅读
自定义DialogViewLayout 实现Dialog效果
关注公众号每天会更新一道面试题:
网友评论