Android Dagger2 @Component的dependencies属性用法

一个Component可以通过dependencies依赖另一个Component,可以获取到另一个Component提供的依赖

具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public interface Person {
String saySomething();
}

public class Student implements Person {

public String name;

public Student() {
this.name = "野猿新一";
}

@Override
public String saySomething() {
return String.format("我的名字叫%s啦", name);
}
}

Click and drag to move

1
2
3
4
5
6
7
@Module
public class PersonModule {
@Provides
public Person providePerson() {
return new Student();
}
}

Click and drag to move

注意这里为Person单独创建了一个Component然后依赖PersonModule,而不是直接把PersonModule设置给MainActivityModule

而且里面的getPerson()方法单纯提供Person对象,不像MainActivityModule中的inject()方法用于注入

1
2
3
4
@Component(modules = PersonModule.class)
public interface PersonComponent {
Person getPerson();
}

Click and drag to move

这里有别于依赖于Module的写法@Component(modules = PersonModule.class),而是直接依赖PersonComponent

1
2
3
4
@Component(dependencies = PersonComponent.class)
public interface MainActivityComponent {
void inject(MainActivity activity);
}

Click and drag to move

这里需要注意的是personComponent()方法必须调用且传递一个PersonComponent对象进入,否则在运行时会报如下错误

实现代码

1
2
3
4
Caused by: java.lang.IllegalStateException: com.him.hisapp.PersonComponent must be set
at com.him.hisapp.DaggerMainActivityComponent$Builder.build(DaggerMainActivityComponent.java:45)
at com.him.hisapp.MainActivity.onCreate(MainActivity.java:20)
at android.app.Activity.performCreate(Activity.java:6041)

Click and drag to move

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class MainActivity extends AppCompatActivity {

@Inject
Person person;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

DaggerMainActivityComponent.builder()
.personComponent(DaggerPersonComponent.create())
.build()
.inject(this);
TextView textView = findViewById(R.id.text);
textView.setText(person.saySomething());
}
}

Click and drag to move

DaggerMainActivityComponent源码解析

我们主要看下Dagger为我们生成的DaggerMainActivityComponent的源码,里面依赖了PersonComponent

在Builder.build()方法调用是会判断personComponent是否为空,空的话会抛异常,至于为什么不在为空的时候直接new一个DaggerPersonComponent出来目前我还不知道原因,还请有知道的读者评论说明下

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public final class DaggerMainActivityComponent implements MainActivityComponent {
private PersonComponent personComponent;

private DaggerMainActivityComponent(Builder builder) {
initialize(builder);
}

public static Builder builder() {
return new Builder();
}

@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.personComponent = builder.personComponent;
}

@Override
public void inject(MainActivity activity) {
injectMainActivity(activity);
}

@CanIgnoreReturnValue
private MainActivity injectMainActivity(MainActivity instance) {
MainActivity_MembersInjector.injectPerson(
instance,
Preconditions.checkNotNull(
personComponent.getPerson(),
"Cannot return null from a non-@Nullable component method"));
return instance;
}

public static final class Builder {
private PersonComponent personComponent;

private Builder() {}

public MainActivityComponent build() {
if (personComponent == null) {
throw new IllegalStateException(PersonComponent.class.getCanonicalName() + " must be set");
}
return new DaggerMainActivityComponent(this);
}

public Builder personComponent(PersonComponent personComponent) {
this.personComponent = Preconditions.checkNotNull(personComponent);
return this;
}
}
}

Click and drag to move

注入的流程

我们再看下Dagger为我们生成的代码再注入的整个过程中做了哪些工作

首先从MainActivity中调用DaggerMainActivityComponent.inject()开始,记得必须调用personComponent设置依赖的Component

1
2
3
4
DaggerMainActivityComponent.builder()
.personComponent(DaggerPersonComponent.create())
.build()
.inject(this);

Click and drag to move

看下DaggerMainActivityComponent中的Builder代码,卡夏是如何设置personComponent的和在build()的时候如果personComponent为空会抛出异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static final class Builder {
private PersonComponent personComponent;

private Builder() {}

public MainActivityComponent build() {
if (personComponent == null) {
throw new IllegalStateException(PersonComponent.class.getCanonicalName() + " must be set");
}
return new DaggerMainActivityComponent(this);
}

public Builder personComponent(PersonComponent personComponent) {
this.personComponent = Preconditions.checkNotNull(personComponent);
return this;
}
}

Click and drag to move

DaggerMainActivityComponent的inject()方法内部调用了injectMainActivity()方法

1
2
3
4
@Override
public void inject(MainActivity activity) {
injectMainActivity(activity);
}

Click and drag to move

DaggerMainActivityComponent的injectMainActivity()方法内部调用了MainActivity_MembersInjector.injectPerson()方法来完成Person的依赖注入,传入MainActivity对象和一个Person实例,而这个Person实例就是由PersonComponent的gerPerson()方法提供的

1
2
3
4
5
6
7
8
9
@CanIgnoreReturnValue
private MainActivity injectMainActivity(MainActivity instance) {
MainActivity_MembersInjector.injectPerson(
instance,
Preconditions.checkNotNull(
personComponent.getPerson(),
"Cannot return null from a non-@Nullable component method"));
return instance;
}

Click and drag to move

我们在看下DaggerPersonComponent的getPerson()方法,里面调用了PersonModule_ProvidePersonFactory.proxyProvidePerson()

1
2
3
4
@Override
public Person getPerson() {
return PersonModule_ProvidePersonFactory.proxyProvidePerson(personModule);
}

Click and drag to move

看下PersonModule_ProvidePersonFactory.proxyProvidePerson()方法内部就明白了Persong对象最终是由PersonModule提供的

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

Click and drag to move

最终再看下MainActivity_MembersInjector.injectPerson()方法,里面把生成的person对象赋值给MainActivity的person变量,最终完成依赖的注入

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

Click and drag to move

总结以上的注入流程就是

MainActivityComponent依赖PersonComponent

PersonComponent依赖PersonModule

所以最终的Person对象是由Module提供的