Google官方MVP+Dagger2架构 dagger2详解

时间:2023-01-18 21:14:48

前言:

dagger2是大家项目中使用比较频繁的一个google开源框架,它旨在解决Android 中的依赖注入,

降低层级之间的耦合性,简化了我们在项目中对象实例化操作;


dagger2 在Android studio 3.0中的引入

annotationProcessor "com.google.dagger:dagger-compiler:2.11"

provided 'org.glassfish:javax.annotation:10.0-b28'

compile "com.google.dagger:dagger:2.11"

compile "com.google.dagger:dagger-android:2.11"

compile "com.google.dagger:dagger-android-support:2.11"

annotationProcessor "com.google.dagger:dagger-android-processor:2.11"



引入后,我们如何学习使用dagger2呢?

1、dagger2中的Inject,Component,Module,Provides等注解代表什么意思,起什么作用?

2、怎样把dagger2应用到具体项目中?


依赖注入:

就是目标类(目标类需要进行依赖初始化的类,下面都会用目标类一词来指代)中所依赖的其他的类的初始化过程,

不是通过手动编码的方式创建,而是通过技术手段可以把其他的类的已经初始化好的实例自动注入到目标类中。

class A{ //A就是目标类

         public B b;//B 就是依赖的类;

}

通过技术手段把初始化好的B类赋值给A类;

@Inject 是什么?

先看一行代码

class A{
B b = new B(...);
C c = new C();
D d = new D(new E());
F f = new F(.....);
}

上面的代码完全没任何问题,但是总感觉创建对象的这些代码基本都是重复的体力劳动,那何尝不想个办法,

把这些重复的体力劳动用一种自动化的、更省力的方法解决掉,这样就可以让开发的效率提高,可以把精力集中在重要的业务上了。

我们可以用注解(Annotation)来标注目标类中所依赖的其他类,同样用注解来标注所依赖的其他类的构造函数

那注解的名字就叫Inject

 class A{
@Inject
B b;
}

class B{
@Inject
B(){
}
}

这样我们就可以让目标类中所依赖的其他类与其他类的构造函数之间有了一种无形的联系。

但是要想使它们之间产生直接的关系,还得需要一个桥梁来把它们之间连接起来。

那这个桥梁就是Component了。


@Component又是什么?

Component也是一个注解类,一个类要想是Component,必须用Component注解来标注该类,并且该类是接口或抽象类。

上文中提到Component在目标类中所依赖的其他类与其他类的构造函数之间可以起到一个桥梁的作用。

那么是如何起到桥梁作用的呢?

 

Component需要引用到目标类(也就是A类)的实例,Component会查找目标类中用Inject注解标注的属性,

查找到相应的属性后会接着查找该属性对应的用Inject标注的构造函数(这时候就发生联系了),

剩下的工作就是初始化该属性的实例并把实例进行赋值。因此我们也可以给Component叫另外一个名字注入器(Injector

Google官方MVP+Dagger2架构 dagger2详解

Component现在是一个注入器,就像注射器一样,Component会把目标类依赖的实例注入到目标类中,来初始化目标类中的依赖。

Component如果把初始化好的B赋值给A中的b呢?

有两种方式:

1、通过inject 

class A{

@inject 

public B b;

}

class B{

public String name;

@inject

public B(){

}

}

在A中可以直接拿到B;

2、通过module提供B的实例通过component桥梁,赋值给A;

@module是什么?

看一行代码:

@module

class activityModule{

@provide

       B provideB(){

            return new B();

       }

}

Module其实是一个简单工厂模式,Module里面的方法基本都是创建类实例的方法。

接下来问题来了,因为component是注入器(injector),我们怎么能让component与module有联系呢?

component新职责:

        Component是注入器,它一端连接目标类,另一端连接目标类依赖实例,它把目标类依赖实例注入到目标类中。

上文中的Module是一个提供类实例的类,所以Module应该是属于Component的实例端的(连接各种目标类依赖实例的端),Component的新职责就是管理好Module,Component中的modules属性可以把Module加入Component,

modules可以加入多个Module。


那接下来的问题是怎么把Module中的各种创建类的实例方法与目标类中的用Inject注解标注的依赖产生关联,那Provides注解就该登场了。

Provides最终解决第三方类库依赖注入问题

         Module中的创建类实例方法用Provides进行标注,Component在搜索到目标类中用Inject注解标注的属性后,Component就会去Module中去查找用Provides标注的对应的创建类实例方法,这样就可以解决第三方类库用dagger2实现依赖注入了。

也就是上面module类中的@provide,负责把创建实例的方法公开出去;

总结:

Inject,Component,Module,Provides是dagger2中的最基础最核心的知识点。奠定了dagger2的整个依赖注入框架

  • Inject主要是用来标注目标类的依赖和依赖的构造函数
  • Component它是一个桥梁,一端是目标类,另一端是目标类所依赖类的实例,它也是注入器(Injector)负责把目标类所依赖类的实例注入到目标类中,同时它也管理Module。
Module是一个 简单工厂模式 ,Module可以包含创建类实例的方法,这些方法用Provides来标注。

关联起来:

         class A{

                @inject

                public B b;

         }

        class B{

                @inject

                public B(){

                }

          }

目标类A 依赖了类B,要想在A类中使用B就需要实例化B,component 负责把实例化好的B赋值给A类中的b,

而component并不具备初始化B的能,使用component就需要到提供B的地方去拿,这个地方就是Module工厂,module工厂如下:

@module

public class ModuleTest{

               @provide

              B provideB(){

                   return new B();

              }

}

component是如果拿到module中的B的呢,看一下component如何操作:

@component(modules = {ModuleTest.class})

public interface TestComponent{

                  void inject(AActivity A);

}

也就是component通过modules引用了module拿到B;、

为讲解完,下一篇 dagger2 详解2


参考链接 http://www.jianshu.com/p/cd2c1c9f68d4