美文网首页
Dagger2 依赖注入使用和分析

Dagger2 依赖注入使用和分析

作者: 东东东鲁 | 来源:发表于2016-08-24 14:29 被阅读242次

    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>了,不信你打印出来看看。

    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 用起来,如果有不明白的,欢迎留言交流。

    公众号

    相关文章

      网友评论

          本文标题:Dagger2 依赖注入使用和分析

          本文链接:https://www.haomeiwen.com/subject/haznsttx.html