dagger2个人学习总结___

来源:互联网 发布:水煮鱼皇后的淘宝店 编辑:程序博客网 时间:2024/05/07 05:56

参考链接:http://android.jobbole.com/82694/


Inject的使用

classA{
      Bb=newB(...);
      Cc=newC();
      Dd=newD(newE());
      Ff=newF(.....);
}
上面的代码完全没任何问题,但是总感觉创建对象的这些代码基本都是重复的体力劳动,那何尝不想个办法,把这些重复的体力劳动用一种自动化的、更省力的方法解决掉,这样就可以让开发的效率提高,可以把精力集中在重要的业务上了。

我们可以用注解(Annotation)来标注目标类中所依赖的其他类,同样用注解来标注所依赖的其他类的构造函数,那注解的名字就叫Inject。
classA{
        @Inject
        Bb;
  }
 
  classB{
      @Inject
      B(){
      }
  }
这样我们就可以让目标类中所依赖的其他类与其他类的构造函数之间有了一种无形的联系。但是要想使它们之间产生直接的关系,还得需要一个桥梁来把它们之间连接起来。那这个桥梁就是Component了。

Component是什么?

Component也是一个注解类,一个类要想是Component,必须用Component注解来标注该类,并且该类是接口或抽象类。我们不讨论具体类的代码,我想从抽象概念的角度来讨论Component。上文中提到Component在目标类中所依赖的其他类与其他类的构造函数之间可以起到一个桥梁的作用。

那我们看看这桥梁是怎么工作的:


Component需要引用到目标类的实例,Component会查找目标类中用Inject注解标注的属性,查找到相应的属性后会接着查找该属性对应的用Inject标注的构造函数(这时候就发生联系了),剩下的工作就是初始化该属性的实例并把实例进行赋值。因此我们也可以给Component叫另外一个名字注入器(Injector)

小结下
目标类想要初始化自己依赖的其他类:

  • 用Inject注解标注目标类中其他类
  • 用Inject注解标注其他类的构造函数
  • 若其他类还依赖于其他的类,则重复进行上面2个步骤
  • 调用Component(注入器)的injectXXX(Object)方法开始注入(injectXXX方法名字是官方推荐的名字,以inject开始)

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

Module

现在有个新问题:项目中使用到了第三方的类库,第三方类库又不能修改,所以根本不可能把Inject注解加入这些类中,这时我们的Inject就失效了。那我们可以封装第三方的类库,封装的代码怎么管理呢,总不能让这些封装的代码散落在项目中的任何地方,总得有个好的管理机制,那Module就可以担当此任。可以把封装第三方类库的代码放入Module中,像下面的例子:

 @Module
    publicclassModuleClass{
          //A是第三方类库中的一个类
          AprovideA(){
              returnA();
          }
    }
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实现依赖注入了。

总结

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

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

dagger2中Scope(作用域),Qualifier(限定符),Singleton(单例),SubComponent等都是对dagger2中整个注入依赖注入框架进行的补充,我们后面会继续讲解,敬请期待……




—————————————————————————————————————————————————————————
Dagger2 主要提供了6种注解,这里我主要讲其中的四种
@Inject @Provide @Module @Component

Dagger2是通过依赖注入完成类的初始化。
这个过程需要三部分:
依赖提供方,依赖注入容器,依赖需求方

@Inject 
Inject主要有两个作用
1.作为依赖注提供方使用:在构造函数上,通过标记构造函数让Dagger2来使用(Dagger2通过Inject标记可以在需要这个类实例的时候来找到这个构造函数并把相关实例new出来)从而提供依赖
2.作为依赖需求方:标记在需要依赖的变量Dagger2会帮助初始化,被我们使用。


@Provide 
用Provide来标注一个方法,该方法可以在需要提供依赖时被调用,变量赋值。provide主要用于标注Module里的方法

@Module 
用Module标注的类是专门用来提供依赖的。注意Module类是提供依赖的一个集合,通常它自身是需要被依赖的。而真正被依赖的都是通过@Provide标注的方法提供,所以@Module和@Provide是联合使用的。

@Component 
Component一般用来标注接口,被标注了Component的接口在编译时会产生相应的类的实例来作为提供依赖方和需要依赖方之间的桥梁,把相关依赖注入到其中。


对上述内容请记住依赖注入过程需要三部分:
依赖提供方,依赖注入容器,依赖需求方
对上述描述不清楚的,请先看下面的案例,再去理解上面的内容。

案例
常规做法
我们要在TestUser 中创建一个User

public class User {
    String userName;
    int age;
}

如果我们想使用User 我们需要new出来然后使用
 public class TestUser {
    User user;
    public static void main(String[] arg) {
        TestUser testUser = new TestUser();
        testUser.user = new User();
        testUser.user.userName = "name";
    }
}

在上述例子中我们如果希望使用User我们需要new一个User然后才能使用
下面我们通过Dragger2去完成上述过程
依赖注入方
通过@Inject和@Module&&@Provide可以去完成依赖注入方
先讲@Module&&@Provide
我们在TestUser 创建了一个@Module TestUserModule

@Module
public class TestUserModule {
 @Provides    
  User provideUser(){
      return new User();
  }
}


我们通过上述代码就完成的依赖注入方。这里解释一下@Module是一个依赖提供方的合集,比如我们现在希望TestUserModule 同时提供一个Account

 @Module
 public class TestUserModule {
 @Provides
  User provideUser(){
      return new User();
  }
  @Provides
  Account provideAccount(){
      return new Account();
  }
}

依赖注入容器
依赖注入容器只是一个接口,用来描述被注入的对象TestUser 需要哪些modules = TestUserModule.class

@Component(modules = TestUserModule.class)
public interface TestUserComponent {
  void inject(TestUser testUser);
}
注入容器本身只是一个接口interface

依赖需求方

public class TestUser {
  @Inject
  User user;
  public static void main(String[] arg) {
      TestUser testUser = new TestUser();
      DaggerTestUserComponent.builder().build().inject(testUser);
      System.out.println(testUser.user.name);
  }
}

我们要打印出name System.out.println(testUser.user.name);
在使用User前要做两件事情

DaggerTestUserComponent.builder().build().inject(testUser);

DaggerTestUserComponent是在编译后编译器帮我们生成的。生成的格式是Dagger+我们自定义的容器
@Inject
User user;
通过我们刚刚的DaggerTestUserComponent.builder().build().inject(testUser);Dagger2会帮我们把user初始化。
注意事项
@Module
Dagger2是怎么选择依赖提供的呢,规则是这样的:
步骤1:查找Module中是否存在创建该类的方法。
步骤2:若存在创建类方法,查看该方法是否存在参数
步骤2.1:若存在参数,则按从步骤1开始依次初始化每个参数
步骤2.2:若不存在参数,则直接初始化该类实例,一次依赖注入到此结束
步骤3:若不存在创建类方法,则查找Inject注解的构造函数,看构造函数是否存在参数
步骤3.1:若存在参数,则从步骤1开始依次初始化每个参数
步骤3.2:若不存在参数,则直接初始化该类实例,一次依赖注入到此结束


0 0
原创粉丝点击