概述:第一篇基本阐明了Dagger2的使用,本篇基于上一篇的Demo来对源码进行分析。
上一篇提到,Dagger2基本分为三个部分。第一部分是创建对象实例。第二部分是引用对象实例。第三部分是利用注入器将两者关联。那么就一个一个分析,先看第一部分:
一 创建对象实例
通过在构造器上加入@Inject来创建实例
public class Student {
@Inject
public Student() {
}
}
然后进行编译,我们会在 app\build\generated\source\apt\debug对应的目录下找到Student_Factory这个类。这个是Dagger2根据在构造器上的@Inject这个注解,自己生成的。我们看一下这个类具体是什么样的:
public final class Student_Factory implements Factory<Student> {
private static final Student_Factory INSTANCE = new Student_Factory();
@Override
public Student get() {
return provideInstance();
}
public static Student provideInstance() {
return new Student();
}
public static Student_Factory create() {
return INSTANCE;
}
public static Student newStudent() {
return new Student();
}
}
一眼看过去,大概就明白,这是一个Student的工厂类,通过provideInstance来自己new一个Student实例,然后通过get方法来获取自己创建出来的实例。
二 引用对象实例
public class MainActivity extends AppCompatActivity {
@Inject
Student student;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
加上这个之后,再进行编译,我们会发现,在同样的目录下又多了一个类,叫做MainActivity_MembersInjector,打开这个类,我们来看一下:
public final class MainActivity_MembersInjector implements MembersInjector<MainActivity> {
private final Provider<Student> studentProvider;
public MainActivity_MembersInjector(Provider<Student> studentProvider) {
this.studentProvider = studentProvider;
}
public static MembersInjector<MainActivity> create(Provider<Student> studentProvider) {
return new MainActivity_MembersInjector(studentProvider);
}
@Override
public void injectMembers(MainActivity instance) {
injectStudent(instance, studentProvider.get());
}
public static void injectStudent(MainActivity instance, Student student) {
instance.student = student;
}
}
注意看injectStudent方法,其实就是Student这个实例对象的引用,给了MainActivity中的Student。第一部分其实已经把Student对象创建好了,现在要做的就是把他们关联起来。于是就用到了注入器:
三 将两者进行关联
这里需要两步操作,第一:先生成注入器:
@Component
public interface MainComponent {
void inject(MainActivity activity);
}
此时对项目进行编译,会再生成一个类DaggerMainComponent:
public final class DaggerMainComponent implements MainComponent {
private DaggerMainComponent(Builder builder) {}
public static Builder builder() {
return new Builder();
}
public static MainComponent create() {
return new Builder().build();
}
@Override
public void inject(MainActivity activity) {
injectMainActivity(activity);
}
private MainActivity injectMainActivity(MainActivity instance) {
MainActivity_MembersInjector.injectStudent(instance, new Student());
return instance;
}
public static final class Builder {
private Builder() {}
public MainComponent build() {
return new DaggerMainComponent(this);
}
}
}
大概理一下,这个类其实是通过builder构建器模式创建对象,然后通过调用inject方法来完成注入。到这一步并不是说就注入完成了,这个注入操作得我们手动写代码完成:
public class MainActivity extends AppCompatActivity {
@Inject
Student student;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//在这里完成手动注入
DaggerMainComponent
.builder()
.build()
.inject(this);
}
}
这里也能体现出来我们上面的分析,通过构建器创建对象,然后调用inject把MainActivity传进去,最后看这几个方法:
@Override
public void inject(MainActivity activity) {
injectMainActivity(activity);
}
private MainActivity injectMainActivity(MainActivity instance) {
MainActivity_MembersInjector.injectStudent(instance, new Student());
return instance;
}
//这个方法是在MainActivity_MembersInjector这个类里面的,这里写一块是为了展示
public static void injectStudent(MainActivity instance, Student student) {
instance.student = student;
}
至此,其实就应该很清楚,为什么我们通过那几个注解,就可以获取到需要注入的实例化对象了。这里还需要进行补充的是,第一部分的实例化对象有两种方式,除了在构造器上加@Inject注解,还可以通过@Module模块来提供对象,那么接下来就看一下@Module是如何提供实例化对象的。
首先把构造器上的@Inject注解注释掉,然后创建Module类
@Module
public class MainModule {
@Provides
static Student provideStudent(){
return new Student();
}
}
然后再编译一下,会发现又生成一个新的类MainModule_ProvideStudentFactory:
public final class MainModule_ProvideStudentFactory implements Factory<Student> {
private static final MainModule_ProvideStudentFactory INSTANCE =
new MainModule_ProvideStudentFactory();
@Override
public Student get() {
return provideInstance();
}
public static Student provideInstance() {
return proxyProvideStudent();
}
public static MainModule_ProvideStudentFactory create() {
return INSTANCE;
}
public static Student proxyProvideStudent() {
return Preconditions.checkNotNull(
MainModule.provideStudent(), "Cannot return null from a non-@Nullable @Provides method");
}
}
注意看这个provideInstance,通过构造器生成的对象,这里面是直接返回new Student(),而通过Module,这里面是调用了proxyProvideStudent()这个方法,而这个方法又会调用MainModule.provideStudent()。这个恰恰是我们手动写的provideStudent,在里面我们自己new了一个Student。
总结:通过对于源码的分析,我们可以更清楚的了解到为什么这么用。这样在遇到问题的时候能更好的通过源码的角度对问题进行分析。