android Dagger2 @Module和@Provides 依赖注入
通过@Inject提供对象来依赖注入有以下两个缺点
- 如果要注入的对象属于某个第三方库中的类,那么我们是无法在在这个类的构造方法上添加@Inject注解的
- 如果要注入的对象是个abstract抽象类或者Interface接口,那么这个类似没有构造方法的,也无法添加@Inject注解
要解决以上问题,这时候就需要@Module和@Provides这对好基友上场了
二话不说,直接上代码
public interface Person {
String saySomething();
}
public class Student implements Person {
public String name;
// 这边不需要再用@Inject了
public Student() {
this.name = "野猿新一";
}
@Override
public String toString() {
return String.format("我的名字叫%s啦", name);
}
@Override
public String saySomething() {
return toString();
}
}
@Module
public class MainModule {
// 注意返回类型要明确是Person,而不能是子类Student
// 这里我们就能够提供了一个接口的实例了
@Provides
public Person providePerson() {
return new Student();
}
}
// 这里记得加载module
@Component(modules = MainModule.class)
public interface MainActivityComponent {
void inject(MainActivity activity);
}
public class MainActivity extends AppCompatActivity {
// 这里声明的是一个接口
@Inject
Person person;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerMainActivityComponent.create().inject(this);
TextView textView = findViewById(R.id.text);
textView.setText(person.saySomething());
}
}
运行结果,成功注入了Person对象
生成代码解析
Dagger为我们生成了很多代码,我们看下注入的流程
DaggerMainActivityComponent和MainActivity_MemberInjector在前面的文章中已经有介绍就不黏贴了
我们这次主要看下跟@Module和@Provides有关的MainModule_ProvidePersonFactory的代码,代码很简单,通过module来提供注入的对象
public final class MainModule_ProvidePersonFactory implements Factory<Person> {
private final MainModule module;
public MainModule_ProvidePersonFactory(MainModule module) {
this.module = module;
}
@Override
public Person get() {
return provideInstance(module);
}
public static Person provideInstance(MainModule module) {
return proxyProvidePerson(module);
}
public static MainModule_ProvidePersonFactory create(MainModule module) {
return new MainModule_ProvidePersonFactory(module);
}
public static Person proxyProvidePerson(MainModule instance) {
return Preconditions.checkNotNull(
instance.providePerson(), "Cannot return null from a non-@Nullable @Provides method");
}
}
我们再看下整个的注入流程的代码
DaggerMainActivityComponent.create().inject(this);
DaggerMainActivityComponent中的相关代码
DaggerMainActivityComponent内部的建造器,Module在这里生成
public static final class Builder {
private MainModule mainModule;
private Builder() {}
public MainActivityComponent build() {
if (mainModule == null) {
this.mainModule = new MainModule();
}
return new DaggerMainActivityComponent(this);
}
public Builder mainModule(MainModule mainModule) {
this.mainModule = Preconditions.checkNotNull(mainModule);
return this;
}
}
@Override
public void inject(MainActivity activity) {
injectMainActivity(activity);
}
@CanIgnoreReturnValue
private MainActivity injectMainActivity(MainActivity instance) {
MainActivity_MembersInjector.injectPerson(
instance, MainModule_ProvidePersonFactory.proxyProvidePerson(mainModule));
return instance;
}
MainModule_ProvidePersonFactory中的proxyProvidePerson()方法,返回由module提供的Person对象
public static Person proxyProvidePerson(MainModule instance) {
return Preconditions.checkNotNull(
instance.providePerson(), "Cannot return null from a non-@Nullable @Provides method");
}
MainActivity_MembersInjector中的injectPerson()方法,将提供的Person对象赋值给Activity的person成员变量,完成注入
public static void injectPerson(MainActivity instance, Person person) {
instance.person = person;
}