1,以前的博客也写了两篇关于Dagger2,但是感觉自己使用的时候还是云里雾里的,更不谈各位来看博客的同学了,所以今天打算和大家再一次的入坑试试,最后一次了,保证最后一次了。
2,接入项目
在项目的Gradle添加如下代码
dependencies { classpath 'com.android.tools.build:gradle:2.3.0' // 添加android-apt 插件 classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' }
在app中的Gradle中添加导入
// 应用插件 apply plugin: 'com.neenbedankt.android-apt' // dagger 2 的配置 compile 'com.google.dagger:dagger:2.4' apt 'com.google.dagger:dagger-compiler:2.4' compile 'org.glassfish:javax.annotation:10.0-b28'// 添加java 注解库
简单的注解标签的介绍,由于之前写过一篇博客和大家思考过为什么使用Dagger2(它这么难使用为什么还要使用!!),并且还有一些常见注解标签的使用,所以这里就不和大家废话这么引入了,直接上干货
@Inject Inject主要有两个作用,一个是使用在构造函数上,通过标记构造函数让Dagger2来使用(Dagger2通过Inject标记可以在需要这个类实例的时候来找到这个构造函数并把相关实例new出来)从而提供依赖,另一个作用就是标记在需要依赖的变量让Dagger2为其提供依赖。 @Provide 用Provide来标注一个方法,该方法可以在需要提供依赖时被调用,从而把预先提供好的对象当做依赖给标注了@Injection的变量赋值。provide主要用于标注Module里的方法 @Module 用Module标注的类是专门用来提供依赖的。有的人可能有些疑惑,看了上面的@Inject,需要在构造函数上标记才能提供依赖,那么如果我们需要提供的类构造函数无法修改怎么办,比如一些jar包里的类,我们无法修改源码。这时候就需要使用Module了。Module可以给不能修改源码的类提供依赖,当然,能用Inject标注的通过Module也可以提供依赖 @Component Component一般用来标注接口,被标注了Component的接口在编译时会产生相应的类的实例来作为提供依赖方和需要依赖方之间的桥梁,把相关依赖注入到其中。 @Singleton 该注解就是通过@scope定义的注解,一般用于提供全局单例。
现在在实际场景中有这种情况,存在学生在老师的课堂上上课,那么一个学生可能存在多个老师,而一个老师也可能存在多个学生。这里我们为了方便解释,就直接转换成1对1的模式即一个学生只有一个老师,一个老师只有一个学生,然我们来看看转换成我们的java对象是什么样的,首先创建学生实体类
Student.java
public class Student { private int id; private String name; private Course[] course; public Student() { System.out.println("Student create!!!"); } public Student(int id, String name, Course[] course) { this.id = id; this.name = name; this.course = course; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Course[] getCourse() { return course; } public void setCourse(Course[] course) { this.course = course; } public void startLessons() { System.out.println("开始上课了"); } }
我们的学生有一些基本的属性,如id、姓名、所学的课程,还有上课的动作。再看看我们创建老师类
public class Teacher { Student student; public Teacher() { student = new student(); } public void teacher() { student.startLessons(); } }
这里我们就有一个问题了,我们老师类中需要一个学生的对象,而按照以前的方法我们肯定是在老师的构造方法中传递学生对象,毫无疑问肯定是new Student创建学生对象的,这里我们要使用Dagger2来代替(至于为什么要使用Dagger2代替,和代替之后有什么好处我以前写过,这里就不和大家废话了)
首先在确定是我们Teacher类中的student属性需要Student对象,所以添加@Inject注解标签
@Inject Student student;
而我们Dagger2要知道到底我是调用那个构造函数来创建Student对象啊,所以要在Student类中构造函数中添加@Inject标签,标明你Dagger2是要在这个构造方法里面创建的
public class Student { private int id; private String name; private Course[] course; @Inject public Student() { System.out.println("Student create!!!"); } public Student(int id, String name, Course[] course) { this.id = id; this.name = name; this.course = course; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Course[] getCourse() { return course; } public void setCourse(Course[] course) { this.course = course; } public void startLessons() { System.out.println("开始上课了"); } }
然后我们 Student中对象被创建了,而我们Teacher中需要这个student对象,这时候我们差一个桥梁来链接这两个类,从而让我们被创建的student对象运送到需要它的地方,所以现在我们需要使用@Component标签,来修饰我们自定义的一个接口,创建TeacherComponent接口,并使用@Component注解标签修饰,创建inject方法(这里很多看过不少Dagger2文章的同学坑定会有疑问,这里的inject是固定方法名吗,能不能使用injectA啊之类的,先把问题留着,我们后面再讲)
package com.qianmo.rxjavatext; import dagger.Component; /** * Created by Administrator on 2017/4/20 0020. * E-Mail:543441727@qq.com */ @Component public interface TeacherComponent { void inject(Teacher teacher); }
再在我们Teacher类中初始化
public Teacher() { DaggerTeacherComponent.builder().build().inject(this); }