Dagger2 依赖注入使用和分析
1. Dagger2是什么
er~~1.1 依赖注入(Dependency Injection)
- 一种软件设计原则,为对象提供了所需要的依赖
- 依赖如果由外部注入进来,更容易被重用
1.2 Dagger2简介
在我们开发过程中,所需使用的对象往往需要依赖其它的对象。比如:
我们使用<code>Retrofit</code>来创建HTTP请求对象时,那么<code>Retrofit</code>还需要一个<code>Gson</code>之类的解析库,以及需要依赖<code>OkHttpClient</code>对象,而<code>OkHttp</code>可能还需要一个<code>Cache</code> 对象,可见,创建一个Retrofit的对象是一个很繁琐的过程。
Dagger2简化了这个过程。我们使用注解来标注依赖之间的关系,Dagger2通过分析注解来生成代码,使依赖关联起来。
- Dagger2是由谷歌维护的一款Java依赖注入框架,由 square 的 Dagger1 flok而来。
- 出于性能考虑,Dagger2不使用反射,注解都是在编译时处理
- 使用Java 依赖注入标准(JSR-330,Dependency Injection for Java)规范,
2. Dagger2怎么用:HelloWord
- 添加<code>android-apt</code>插件,首先在根结点的<code>build.gradle</code>加一行依赖
dependencies {
...
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
- 然后在<code>app/build.gradle</code>中上加插件和Dagger2依赖
apply plugin: 'com.neenbedankt.android-apt'
...
dependencies {
...
apt 'com.google.dagger:dagger-compiler:2.2'
compile 'com.google.dagger:dagger:2.2'
provided 'org.glassfish:javax.annotation:10.0-b28'
}
- 好,现在我们来写一个 HelloWorld 程序,从外部注入一个<code>"Hello World!"</code>到<code>MainActivity</code>,首先我们需要一个<code>Module</code> 用来提供所需的依赖:
@Module
public class HelloModule {
@Provides @Singleton
public String providesHelloMessage() {
return "Hello World!";
}
}
- 然后我们使用<code>Component</code>来标注<code>MainActivity</code>和<code>HelloModule</code>之间的关系,我们只需要定义这样一个接口,它的实现类会由Dagger2编译后生成:
@Singleton
@Component(
modules = HelloModule.class
)
public interface HelloComponent {
void inject(MainActivity activity);
}
- 执行编译操作让Dagger2生成<code>HelloComponent</code>的实现类<code>DaggerHelloComponent</code>,最后就可以在<code>MainActivity</code>中注入了:
public class MainActivity extends AppCompatActivity {
@Inject String helloMessage;
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
HelloComponent component = DaggerHelloComponent.builder()
.helloModule(new HelloModule(this))
.build();
component.inject(this);
}
}
嗯,这样<code>HelloModule</code>中的<code>Hello World!</code>字符串就被注入到<code>MainActivity</code>中的<code>helloMessage</code>了,不信你打印出来看看。
- Demo源码:dagger2-demo-helloworld
3. Dagger2 分析
-
以上HelloWorld的例子,由这几个部分组成:
HelloWord
@Module 和 @Provides
首先我们要定义要用到的依赖,这些依赖就放在一个被@Module
标记的类里面。这个类定义了一些方法,每一个方法就是一个工厂,提供所需要的依赖,用@Provides
标记。
@Component
Dagger2通过@Component
来生成代码,Dagger2会生成一个以Dagger
开头的类(比如,DaggerHelloComponent
),它负责实例化所需要的依赖。
@Inject
@Inject
用来声明要被注入的对象,Dagger2通过查找自己的依赖关系,找出和这个对象匹配的返回类型并分配给它,最终这个对象就是之前在@Module
中定义的那个对象。
- 这里可能会有疑问,Dagger2是通过类型来查找的,如果有两个类型相同的依赖怎么办?
答:使用Qualifier
来区分不同的类型。例如:
@Inject @Named("cached") OkHttpClient client;@Inject @Named("non_cached") OkHttpClient client2;
上面代码中的@Named
就是 Dagger2 定义好的一个 Qualifier。我们也可以自己定义 Qualifier:
@Qualifier
@Documented
@Retention(RUNTIME)
public @interface DefaultOkHttp {
}
@Singleton
Dagger2 中可以通过自定义 Scope 注解来指定它的作用范围。如果一个对象的作用范围指定为@Singleton
的话,则是全局唯一的,当应用销毁时才会被销毁。关于自定义 Scope 的更多详细内容可以参考这篇文章:http://frogermcs.github.io/building-userscope-with-dagger2
公众号看了上面的分析,希望大家有所帮助,并且把 Dagger2 用起来,如果有不明白的,欢迎留言交流。