在你读这篇文章时,我假设你已经知道了使用Dagger有什么好处,下面我们开门见山。本偏讲述的是Dagger2的HelloWorld
。希望读者通过本篇文章能了解Dagger2最基本的用法。
1. 添加依赖
compile 'com.google.dagger:dagger:2.14.1'
annotationProcessor 'com.google.dagger:dagger-compiler:2.14.1'
第一个依赖中包含了要使用到的类,第二个依赖用于编译和生成代码。
2. 创建Component
写一个空的Component
,这个Component
可以是接口或者抽象类,必须使用@Component
标注。
@Component
public abstract class HelloComponent {
}
3. 生成DaggerComponent
rebuild工程,前往app/build/source/apt/debug/yourpackage
下面找到相应的Dagger*Component
类,比如我用上述的HelloComponent
,rebuild之后得到一个DaggerHelloComponent
类:
public final class DaggerHelloComponent extends HelloComponent {
private DaggerHelloComponent(Builder builder) {}
public static Builder builder() {
return new Builder();
}
public static HelloComponent create() {
return new Builder().build();
}
public static final class Builder {
private Builder() {}
public HelloComponent build() {
return new DaggerHelloComponent(this);
}
}
}
Dagger基于@Component
标注的类,使用注解处理器生成了一个该类的实现类。该类以”Dagger”与@Component
注解类的类名进行驼峰组合命名,是@Component
注解类的实现类。它内置了构造器Builder
.
通过DaggerHelloComponent.create()
可以得到HelloComponent
类型的DaggerHelloComponent
实例。
通过DaggerHelloComponent.builder()
可以得到DaggerHelloComponent.Builder
的实例,进而通过build()
方法,即DaggerHelloComponent.builder().build()
也能得到HelloComponent
类型的DaggerHelloComponent
实例。
目前来看上述两种获取AppComponent实例的方法是等效的。那它们究竟有什么区别呢?这个我们留在后面再说。
目前,我们虽然能得到由HelloComponent
实例,但是很显然,我们用它什么都干不了。
4. 添加Component
方法
根据官方API,Dagger的Component
必须至少包含一个抽象的Component方法(否则就像上面这样,Component
啥用也没有)。所谓Component
方法,指的是Provision方法或者Members-Injection方法。
+ Provision
方法
Provision
方法类似于Bean
类的Getter
方法,是一种无参方法,该方法返回一个injected
或者provided
类型
Members-Injection
方法
Members-Injection
方法类似于Bean
类的Setter
方法,但是它并不是把入参传给Component
,而是将Component
可提供的对象传给入参的成员。Members-Injection
方法的名字任意,格式正好与Provision
方法相反,有参数无返回值。使用Members-Injection
方法,Component
会向Client
类使用@Inject
修饰的成员提供对象。
下面以injected
类型为例,讲述两种Component
方法的不同用法。最简单地,通过@Inject
修饰一个具体类的无参构造函数就可以得到一个injected
类型了。例如下面的User
。
public class User {
private String mName;
@Inject
public User() {
mName = "JingKe";
}
public String getName() {
return mName;
}
public void setName(String name) {
mName = name;
}
public void say(){
Log.e("User","Hello, I'm "+mName+", I am using a Dagger");
}
}
rebuild,注解处理器根据@Inject
修饰的User
生成一个User_Factory
类如下:
public final class User_Factory implements Factory<User> {
private static final User_Factory INSTANCE = new User_Factory();
@Override
public User get() {
return new User();
}
public static User_Factory create() {
return INSTANCE;
}
}
4.1 使用Provision
方法
在
HelloComponent
中添加一个返回injected
类型的抽象的Provision
方法:@Component public abstract class HelloComponent { abstract User getUser(); }
rebuild工程,在
app/build/source/apt/debug/yourpackage
目录下,Dagger为我们生成新的DaggerHelloComponent
:public final class DaggerHelloComponent extends HelloComponent { private DaggerHelloComponent(Builder builder) {} public static Builder builder() { return new Builder(); } public static HelloComponent create() { return new Builder().build(); } @Override User getUser() { return new User(); } public static final class Builder { private Builder() {} public HelloComponent build() { return new DaggerHelloComponent(this); } } }
新的
DaggerHelloComponent
也覆盖了我们在HelloComponent
中添加的抽象的Provision
方法,返回User
对象。使用
DaggerHelloComponent
的Provision
方法获取对象:public class ComponentActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_component); DaggerHelloComponent.create().getUser().say(); } }
4.2 使用Members-Injection
方法
在
Component
中新建Members-Injection
方法:@Component public abstract class HelloComponent { // public abstract User getUser(); public abstract void inject(ComponentActivity injectionActivity); }
rebuild,生成新的
DaggerHelloComponent
:public final class DaggerHelloComponent extends HelloComponent { //... @Override public void inject(ComponentActivity injectionActivity) {} //... }
这时候我们发现,除了重写了
inject()
抽象方法,给出一个空实现,并没有什么变化。看官别急,继续往下看:在
Client
类中,添加可注入成员,并用@Inject
修饰,这里需要注意在使用这些对象之前,必须调用Members-Injection
方法注入这些对象:public class ComponentActivity extends AppCompatActivity { @Inject User mUser; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_hello_component); // DaggerHelloComponent.create().getUser().say(); DaggerHelloComponent.create().inject(this); mUser.say(); } }
这一次rebuild之后,我们会发现,build目录下增加了一个
ComponentActivity_MembersInjector
类:public final class ComponentActivity_MembersInjector implements MembersInjector<ComponentActivity> { private final Provider<User> mUserProvider; public ComponentActivity_MembersInjector(Provider<User> mUserProvider) { this.mUserProvider = mUserProvider; } public static MembersInjector<ComponentActivity> create(Provider<User> mUserProvider) { return new ComponentActivity_MembersInjector(mUserProvider); } @Override public void injectMembers(ComponentActivity instance) { injectMUser(instance, mUserProvider.get()); } public static void injectMUser(ComponentActivity instance, User mUser) { instance.mUser = mUser; } }
DaggerHelloComponent
也有了实质性的变化:public final class DaggerHelloComponent extends HelloComponent { private DaggerHelloComponent(Builder builder) {} public static Builder builder() { return new Builder(); } public static HelloComponent create() { return new Builder().build(); } @Override public void inject(ComponentActivity injectionActivity) { injectComponentActivity(injectionActivity); } private ComponentActivity injectComponentActivity(ComponentActivity instance) { ComponentActivity_MembersInjector.injectMUser(instance, new User()); return instance; } public static final class Builder { private Builder() {} public HelloComponent build() { return new DaggerHelloComponent(this); } } }
从以上可以看出,
Client
类中的@Inject
成员会对DaggerCompoent
的生成产生影响。注解处理器根据@Inject
成员生成当前Client
类的成员注入器,DaggerComponent
通过用户声明的inject()
方法传参Client
和依赖,然后注入器将依赖设置到Client
的成员,完成成员对象的注入。
两种Component
方法最后达到了同样的目的,如下是打印结果:
E/User: Hello, I'm JingKe, I am using a Dagger
总结
本篇文章讲述了Dagger2最基本的用法,概括为以下步骤:
1. 创建Component
2. 提供injectable
类或者provided
对象
3. 添加Component
方法,Component
方法包括Provision
方法和Members-Injection
方法。
4. 使用Component
提供或注入依赖到Client
类。
下一节我们讲injected
类型之@Inject
.