Dagger2是一款基于Java注解来实现的完全在编译阶段完成依赖注入的开源库,主要用于模块间解耦、提高代码的健壮性和可维护性。Dagger2在编译阶段通过apt利用Java注解自动生成Java代码,然后结合手写的代码来自动帮我们完成依赖注入的工作。
public class Student {
String name = "liu";
Student() {
}
}
有个Student类, 我需要在多个Activity中都创建这个类的对象。需要这么写:
public class MainActivity extends AppCompatActivity {
Student student;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
student = new Student();
}
}
public class MainActivity2 extends AppCompatActivity {
Student student;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
student = new Student();
}
}
public class MainActivity3 extends AppCompatActivity {
Student student;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
student = new Student();
}
}
如果我的Student的构造方法改了,改成有参构造。传了个int,如下所示,那么我需要在每个用到构造方法的地方,都修改一次。有点痛苦, 三个用到的还可以,改改就是了,但是要是二三十个用到了,那真是太难了。
public class Student {
String name = "liu";
int age;
Student(int age) {
this.age=age;
}
}
public class MainActivity extends AppCompatActivity {
@Inject
Student student;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerStudentComponent.create().injectMainActivity(this);
}
}
public class MainActivity2 extends AppCompatActivity {
@Inject
Student student;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerStudentComponent.create().injectMainActivity(this);
}
}
public class MainActivity3 extends AppCompatActivity {
@Inject
Student student;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerStudentComponent.create().injectMainActivity(this);
}
}
就这么一写, Student的对象就初始化完成了, 具体是由下面这个来决定如何构造Student对象的。
@Module
public class StudentModule {
@Provides
public Student getStudent() {
return new Student(99);
}
}
@Component(modules = StudentModule.class)
public interface StudentComponent {
// 送到收货地址 --- 注入到Activity
void injectMainActivity(MainActivity mainActivity);
void injectMainActivity(MainActivity2 mainActivity);
void injectMainActivity(MainActivity3 mainActivity);
void injectMainActivity(MainActivity4 mainActivity);
}
如上面这个购物的例子。买家在网上下单, 然后卖家将商品打包好,交给快递员,快递员将快递送给买家。什么样的东西用什么样的包裹,但是快递员是不知道包裹里面是什么的, 买家也不需要知道商品是怎么生产的,用就完事了。
注入的起点是DaggerStudentComponent.create().injectMainActivity(this);
这个代码。DaggerStudentComponent
这个类是根据@Component(modules = StudentModule.class)
注解动态生成的。DaggerStudentComponent
这个类会实现有这个注解的接口
@Component(modules = StudentModule.class) // 快递员拿到了包裹
public interface StudentComponent {
// 送到收货地址 --- 注入到Activity
void injectMainActivity(MainActivity mainActivity); // 不支持多态功能的
void injectMainActivity(MainActivity2 mainActivity);
void injectMainActivity(MainActivity3 mainActivity);
void injectMainActivity(MainActivity4 mainActivity);
}
再看DaggerStudentComponent.create()
方法做了什么
public static StudentComponent create() {
return builder().build();
}
通过build设计模式构造了StudentComponent 的具体对象。Build的类如下所示。
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;
}
}
所以DaggerStudentComponent.create()
方法就是构造了DaggerStudentComponent
这个对象。而构造方法中进行了一些变量的初始化
private DaggerStudentComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
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);
}
这其中就有几个注射器和一个Student提供者,这里先知道这几个变量在构造方法的时候初始化的。后面再详细分析。
再看DaggerStudentComponent.create().injectMainActivity(this);
中injectMainActivity
方法。实际上这个方法是从StudentComponent
接口中实现的。
@Override
public void injectMainActivity(MainActivity mainActivity) {
mainActivityMembersInjector.injectMembers(mainActivity);
}
注射到MainActivity,就是使用了mainActivityMembersInjector
这个注射器的injectMembers
方法,如下所示:
@Override
public void injectMembers(MainActivity instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
instance.student = studentProvider.get();
}
如果传进来的MainActivity对象为空,则抛出异常,否则mainactivity.student = studentProvider.get();
。
而studentProvider.get();
的具体实现是交由module来实现的
@Override
public Student get() {
return Preconditions.checkNotNull(
module.getStudent(), "Cannot return null from a non-@Nullable @Provides method");
}
这个module也就是我们自己定义的。
@Module
public class StudentModule {
@Provides
public Student getStudent() {
return new Student(99);
}
}
终于我们MainActivity.student这个变量有了值了。
Component将需要Student对象的 对象传给Injector,Injector找Provides要Student对象赋值给student变量。
的确实现了实体与Activity之间的解耦,使用起来也挺方便的。 但是就是编译会比较慢了,需要在编译器生成多个文件,最终也会增加大apk。