android Dagger2 @Module和@Provides 依赖注入

通过@Inject提供对象来依赖注入有以下两个缺点

  • 如果要注入的对象属于某个第三方库中的类,那么我们是无法在在这个类的构造方法上添加@Inject注解的
  • 如果要注入的对象是个abstract抽象类或者Interface接口,那么这个类似没有构造方法的,也无法添加@Inject注解

要解决以上问题,这时候就需要@Module和@Provides这对好基友上场了

二话不说,直接上代码

1
2
3
public interface Person {
String saySomething();
}

Click and drag to move

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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();
}
}

Click and drag to move

1
2
3
4
5
6
7
8
9
@Module
public class MainModule {
// 注意返回类型要明确是Person,而不能是子类Student
// 这里我们就能够提供了一个接口的实例了
@Provides
public Person providePerson() {
return new Student();
}
}

Click and drag to move

1
2
3
4
5
// 这里记得加载module
@Component(modules = MainModule.class)
public interface MainActivityComponent {
void inject(MainActivity activity);
}

Click and drag to move

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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());
}
}

Click and drag to move

运行结果,成功注入了Person对象

imgClick and drag to move

生成代码解析

Dagger为我们生成了很多代码,我们看下注入的流程

imgClick and drag to move

DaggerMainActivityComponent和MainActivity_MemberInjector在前面的文章中已经有介绍就不黏贴了

我们这次主要看下跟@Module和@Provides有关的MainModule_ProvidePersonFactory的代码,代码很简单,通过module来提供注入的对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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");
}
}

Click and drag to move

我们再看下整个的注入流程的代码

1
DaggerMainActivityComponent.create().inject(this);

Click and drag to move

DaggerMainActivityComponent中的相关代码

DaggerMainActivityComponent内部的建造器,Module在这里生成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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;
}
}

Click and drag to move

1
2
3
4
5
6
7
8
9
10
11
@Override
public void inject(MainActivity activity) {
injectMainActivity(activity);
}

@CanIgnoreReturnValue
private MainActivity injectMainActivity(MainActivity instance) {
MainActivity_MembersInjector.injectPerson(
instance, MainModule_ProvidePersonFactory.proxyProvidePerson(mainModule));
return instance;
}

Click and drag to move

MainModule_ProvidePersonFactory中的proxyProvidePerson()方法,返回由module提供的Person对象

1
2
3
4
public static Person proxyProvidePerson(MainModule instance) {
return Preconditions.checkNotNull(
instance.providePerson(), "Cannot return null from a non-@Nullable @Provides method");
}

Click and drag to move

MainActivity_MembersInjector中的injectPerson()方法,将提供的Person对象赋值给Activity的person成员变量,完成注入

1
2
3
public static void injectPerson(MainActivity instance, Person person) {
instance.person = person;
}

Click and drag to move