Dagger 2从浅到深(一)

Dagger系列:

  1. Dagger 2从浅到深(一)
  2. Dagger 2从浅到深(二)
  3. Dagger 2从浅到深(三)
  4. Dagger 2从浅到深(四)
  5. Dagger 2从浅到深(五)
  6. Dagger 2从浅到深(六)
  7. Dagger 2从浅到深(七)
  8. Dagger 2应用于Android的完美扩展库-dagger.android


Demo地址:

  1. DaggerLearn
  2. Kotlin-Dagger-2-Retrofit-Android-Architecture-Components

概述

在Dagger 2官方文档中,有这么一句话“A fast dependency injector for Android and Java.”,翻译过来的意思就是:适用于Android和Java的快速依赖注入。

这里主要是了解Dagger 2,对依赖注入不多叙述。不理解依赖注入的,可以参考以下博客:

  1. 控制反转(IoC)与依赖注入(DI)
  2. 浅谈依赖注入
  3. 理解依赖注入(IOC)和学习Unity

Gradle配置

对于Gradle插件在2.3以上可以这么配置

dependencies {
  compile 'com.google.dagger:dagger:2.x'
  annotationProcessor 'com.google.dagger:dagger-compiler:2.x'
}

如果Gradle插件在2.3以下,就不得不借用apt插件了:

  1. 在根gradle中

    dependencies {
         ... // 其他classpath
         classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' //添加apt命令
     }
    
  2. 在App.gradle中

    dependencies {
      compile 'com.google.dagger:dagger:2.x'
      apt 'com.google.dagger:dagger-compiler:2.x'
    }
    

@Inject

在Dagger 2中,使用javax.inject.Inject注解来标识需要依赖注入的构造函数和字段,以满足Dagger构造应用应用程序类的实例并满足其依赖性。

@Inject有两项职责:

  • 注解构造函数:通过标记构造函数,告诉Dagger 2可以创建该类的实例(Dagger2通过Inject标记可以在需要这个类实例的时候来找到这个构造函数并把相关实例new出来)从而提供依赖关系。
  • 注解依赖变量:通过标记依赖变量,Dagger2提供依赖关系,注入变量

注解构造函数

这里我们声明了,StudentBean对象,其构造函数被@Inject注解,以便被Dagger 2创建其实例。

public class StudentBean {
    private int no;
    private String name;

    @Inject
    public StudentBean() {
        this.no = 1;
        this.name = "赵四";
    }

    ***
}

测试:

public class StudentActivity extends BaseActivity {

    ***

        @Inject
        StudentBean studentBean;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            ButterKnife.bind(this);
            // Log("student:StudentBean{no=1, name='赵四'}")
            Log.d("test", "student:" + studentBean.toString());
            tvStu.setText(studentBean.toString());
        }

    ***
}

这里简单的注入了一个StudentBean实例,就算完成了。

注解字段

这时,就有一个疑问了,并不是所有的成员变量是基本数据类型,有的成员变量本身就是一个类的实例,这样我们是否还能使用依赖注入呢?既然有这样的疑问,不妨试一下。

  1. 创建AreaBean和ScoreBean,其构造函数均被

    public class AreaBean {
        private String provice;
        private String city;
    
        @Inject
        public AreaBean() {
            this.provice = "四川";
            this.city = "成都";
        }
    
        ***
    }
    
    public class ScoreBean {
        private double chinese;
        private double math;
    
        @Inject
        public ScoreBean() {
            this.chinese = 90.5;
            this.math = 78.0;
        }
    
        ***
    }
    
  2. 修改Student实例,增加两个成员变量,分布是AreaBean、ScoreBean

    public class StudentBean {
        private int no;
        private String name;
    
        @Inject
        AreaBean areaBean;
        @Inject
        ScoreBean scoreBean;
    
        @Inject
        public StudentBean() {
            this.no = 1;
            this.name = "赵四";
        }
    
        ***
    }
    
  3. 测试

    public class StudentActivity extends BaseActivity {

    ***
    
        @Inject
        StudentBean studentBean;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            ButterKnife.bind(this);
            // Log:student:StudentBean{no=1, name='赵四', areaBean=AreaBean{provice='四川', city='成都'},scoreBean=ScoreBean{chinese=90.5, math=78.0}}
            Log.d("test", "student:" + studentBean.toString());
            tvStu.setText(studentBean.toString());
        }
    
    ***
    

    }

从测试结果,可以清晰的看到,即使@Inject注解字段,Dagger依然可以创建相应的实例并注入。


注意:

  • 如果在类中有@Inject注解的字段,但是该字段的没有使用@Inject注解其构造函数。此时,Dagger将在请求时注入这些字段,但不会创建新实例,也就意味着将获得一个空的对象。使用@Inject注释添加一个无参数的构造函数,以指示Dagger也可以创建实例。此时,甚至会出现编译不成功,提示添加Provider方法(后续提到),提供所需实例。
  • Dagger支持方法注入,不过,通常用来构造器或字段的依赖注入。

@Inject不是万能的

@Inject并不是万能,对于未知的事物,还是无能为力的。比如,所熟悉的接口,接口并不能创建实例,这时,我们就不能使用@Inject注解。

  • 接口不能够创建
  • 第三方库的类不能够创建
  • 配置对象必须配置!

结束语

到这里,Dagger 2入门的简单例子已经实现了。简单总结一下:

  1. @Inject注解构造函数,表示该类委托Dagger创建实例
  2. @Inject声明属性变量,表示注入这个依赖。如果这个变量本事是一个实例对象,其构造函数必须使用@Inject注解,或者是通过Provider方法提供。
  3. @Inject并不是万能的。

参考文档

  1. 浅析Dagger2的使用
  2. Android:dagger2让你爱不释手-基础依赖注入框架篇
  3. Android:dagger2让你爱不释手-重点概念讲解、融合篇
  4. Android:dagger2让你爱不释手-终结篇
  5. “一盘沙拉”带你入门Dagger2(一)之HelloWorld
  6. Dagger2图文完全教
  7. 为什么网上这么多dagger2教程,我还写了这篇文章。

你可能感兴趣的:(Dagger)