Android dagger2

什么是dagger2

Dagger2是Dagger的升级版,是一个依赖注入框架,现在由Google接手维护。 恩,这里有个关键字依赖注入,因此我们得先知道什么是依赖注入,才能更好的理解Dagger2。

依赖注入是面向对象编程的一种设计模式,其目的是为了降低程序耦合,这个耦合就是类之间的依赖引起的。

什么是依赖注入?当 A 类中包含一个属性 B 类,就可以说 A 对 B 产生了 依赖。当实例化一个对象的时候,不再需要 new 出一个实例,而是由框架自动的帮你生成一个实例,这就是 注入

简单的说,就是程序运行之前需要某些基础数据,这些基础数据就叫做依赖的数据。

依赖注入有以下几种方式:

  • 通过接口注入
    interface ClassBInterface {
    void setB(ClassB b);
    }

        public class ClassA implements ClassBInterface {
            ClassB classB;
    
            @override
            void setB(ClassB b) {
                classB = b;
            }
        }
    
  • 通过set方法注入
    public class ClassA {
    ClassB classB;

            public void setClassB(ClassB b) {
                classB = b;
            }
        }
    
  • 通过构造方法注入
    public class ClassA {
    ClassB classB;

            public void ClassA(ClassB b) {
                classB = b;
            }
    
  • 通过Java注解
    public class ClassA {
    //此时并不会完成注入,还需要依赖注入框架的支持,如RoboGuice,Dagger2
    @inject ClassB classB;

            ...
            public ClassA() {}
    

在Dagger2中用的就是最后一种注入方式,通过注解的方式,将依赖注入到宿主类中。

在 Android Studio 中配置 Dagger2

Dagger2 是一个通用的 java 库,并不只适用于 Android,这里仅以 Studio 下的 Android 开发示例。
在项目的根 build.gradle 里添加:

    buildscript {
        ...
        dependencies {
            ... 
            //编译时处理注解的插件,生成代码就靠它
            classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
        }
    }

在module的build.gradle添加:

    apply plugin: 'com.neenbedankt.android-apt'

        android{
            ...
        }

    dependencies {
        provided 'org.glassfish:javax.annotation:10.0-b28'
        compile 'com.google.dagger:dagger:2.5'
        compile 'com.google.dagger:dagger-compiler:2.5'
    }

贴上整个gradle:

    apply plugin: 'com.android.application'
    //dagger add
    apply plugin: 'com.neenbedankt.android-apt'

    android {
        compileSdkVersion 24
        buildToolsVersion "24.0.1"
        defaultConfig {
            applicationId "com.example.ibesteeth.gjj_dagger_demo"
            minSdkVersion 17
            targetSdkVersion 24
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    }

    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])

        compile 'com.android.support:appcompat-v7:24.2.0'
        compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha1'
        testCompile 'junit:junit:4.12'

        //dagger2
        compile 'com.google.dagger:dagger:2.4'
        apt 'com.google.dagger:dagger-compiler:2.4'
        //java注解
        compile 'org.glassfish:javax.annotation:10.0-b28'

        //Square
        compile 'com.jakewharton:butterknife:6.1.0'
        compile 'com.squareup.retrofit:retrofit:1.9.0'
        compile 'com.squareup.okhttp:okhttp:2.3.0'
    }

Dagger2 中的注解

@Module

注解一个类,这个类用来提供依赖,或者通俗的说,完成各种对象的实例化 的一个集合。类里面可以包含很多@Provides
注解的方法,每个方法对应一种对象的创建。

@Provides

注解 Module 类里面的方法,Dagger 会在需要创建实例的时候找到这个方法并调用,完成对象的实例化。

这样说可能还是太抽象,看一个实例:

    //apiservice的工厂类
    @Module
    public class ApiServiceModule {

        @Provides
        int getId(){
            return 0;
        }

        @Provides
        String getName(){
            return "testName";
        }

        @Provides
        @Singleton
        ApiService provideApiServiceNull(int id,String name) {
            return new ApiService(id,name);
        }
    }

@Module 注解的含义很简单,它就是告诉 Dagger 框架,这个类里面有可以提供对象创建的方法。所以 Module 类可以理解成一个用来组织对象创建方法的容器,关键是其内部的方法。

我的理解其实就是,生成bean对象的一个辅助类,相当于factory工厂类

注意:任何 Module 类的开头都以 @Module 进行注解。

@Inject

当注解一个属性的时候,表示该属性需要依赖(需要被注入一个对象)。
当注解一个构造函数的时候,表示该构造函数可以提供依赖。需要注意的是,如果被 @Inject 注解的构造函数是带参数的,比如这样:

Android dagger2_第1张图片
inject_moudle.jpg
@Component

前面说了 @Module 提供依赖, @Inject请求依赖,而@Component 就是联系这两者的纽带。
Component 主要说明4件事:

谁来提供依赖
该 Component 依赖哪些其他的 Component
该 Component 为谁提供依赖注入
该 Component 可以提供那些依赖
@Component 注解的是一个接口,比如下面这个接口,表示它可以提供一个 MyApplication 类型的依赖。

对应前面说的4点:

  • module
    参数{}里的类就表示提供依赖的Module类(可以有多个),也就是用@Module
    注解的类
  • dependencies
    表示该 Component 提供的注入类的构造函数中,还依赖其他@Component
    提供的一些类。
  • 有参无反的方法指明该 Component 注入的目标,比如本例中,就说明 MyActivity 中需要 AppComponent 提供的依赖
  • 有反无参的方法指明该 Component 可以提供哪些依赖,或者说暴露哪些依赖。因为这里可能会有疑问,Component 可提供的依赖不就是 Module 里的那些吗?确实没错,但是 Component 也可以有选择的只对外界暴露它的一部分能力,并不一定会声明所有的在 Module 里定义的类。

这个接口可以理解成一份声明,告诉Dagger哪些对象可以被注入,以及谁(Module类中被@Provides
注解的方法)来提供这些依赖。需要注意,只有在 Component 接口中声明了的类,才会被暴露给依赖它的其他 Component。也就是说,Module 类中提供的依赖,并不一定都会在 Component 中声明。
最后,这个接口的实现会由 Dagger 框架自动生成,生成类的名字满足 *Dagger + 你的接口名
的格式。可以在 项目的app-buile
目录下找到生成的代码。后面的使用也主要是跟 Component 的实现类打交道。

我们来重新理一遍上面的注入过程,首先弄清楚以下几个概念:
@Inject 带有此注解的属性或构造方法将参与到依赖注入中,Dagger2会实例化有此注解的类
@Module 带有此注解的类,用来提供依赖,里面定义一些用@Provides注解的以provide开头的方法,这些方法就是所提供的依赖,Dagger2会在该类中寻找实例化某个类所需要的依赖。
@Component 用来将@Inject和@Module联系起来的桥梁,从@Module中获取依赖并将依赖注入给@Inject

参考注入的三种方式
对dagger2的解释挺好

Component--工厂管理员

注意

当module中创建对象的时候,需要传入参数的时候,需要添加传入参数的获取

参考ApiServiceModule类里面的代码

参考这里的解释
github项目地址

参考文档

你可能感兴趣的:(Android dagger2)