Dagger学习 -- 基础概念

目标

了解 Dagger 基本概念

官方定义

Google 对 Dagger 的定义如下:

Dagger is a fully static, compile-time dependency injection framework for both Java and Android. It is an adaptation of an earlier version created by Square and now maintained by Google.

Dagger 是一个为 Java 和 Android 设计的完全静态,编译时依赖注入框架。现在由 Google 维护,它对 Square 开发的早期版本进行了改写。

什么是编译时依赖呢?就是不在运行时依赖,额...Dagger 会通过注解,生成代码,而这个代码跟我们手动写的依赖注入的代码一样。

如果你对『依赖注入』不了解,请看[这篇文章]()(未填的坑)。

Dagger1.x已经废弃,我们以后所说的Dagger就是Dagger2.x。

Dagger 基本概念

Dagger 使用了注解,我们先来最基本的注解的用法。

声明依赖 @Inject

Dagger 使用注解 javax.inject.Inject 来修饰一个类的构造函数,然后就 Dagger 就可以管理它了。当 Dagger 需要 该类的实例时,就会调用这个构造函数来构造它,也会自动实例化该构造函数的参数所需要的实例。

@Inject 也可以修饰一个类的属性,在构造这个类时,Dagger 会将这个属性所需要的对象实例化出来。但是要注意,这个属性的类型构造函数需要注入即也用 @Inject 修饰。

@Inject 还可以修饰一个方法,这样在构造实例后,会立刻调用该方法。并不推荐这样做,因为这就是初始化的工作嘛,都可以在构造函数里做。

class Thermosiphon implements Pump {
  private final Heater heater;

  @Inject
  Thermosiphon(Heater heater) {
    this.heater = heater;
  }

  ...
}

class CoffeeMaker {
  @Inject Heater heater;
  @Inject Pump pump;

  ...
}

但是 @Inject 有他的局限性

  1. 接口不能注入,它没有构造函数。而一个好的设计是面向接口编程
  2. 第三方类库的类,我们不能修改,没法给它加 @Inject
  3. 我们需要的对象可能需要配置,而且每次需要的配置可能还不同

满足依赖 @Provides

以上 @Inject 的问题都可以通过 @Provides 来解决。 @Provides 修饰一个方法,这个方法会提供一个对象,在方法里我们自己实现如何实例化一个对象,如何配置。这个方法也可以有参数,同 @Inject 修饰的构造函数,参数会被注入。

但是,@Inject 修饰的方法只能是一个 Module 的方法可以是静态的或者非静态的。而这个 Module 实际只是一个由 @Module 修饰的普通的类。

约定,@Provides 修饰的方法命名以 provide 开头,@Module 修饰的类以 Module 结尾。

@Module
class DripCoffeeModule {
@Provides static Heater provideHeater() {
return new ElectricHeater();
}

@Provides static Pump providePump(Thermosiphon pump) {
return pump;
}
}

构建对象图

@Inject 和 @Provides 修饰的类组成了一个对象图,而其中的元素因依赖而连接。而应用的入口点,就需要拿到这个图的一个根的集合(这牵扯到数据结构了,数据结构里的树有一个根,而图可以有多个根,从这个根,连接到一系列节点构成一颗树)。Dagger 通过 Component 提供这个图的根的集合。只有拿到 Component, Dagger 才能按照约定构造所有依赖的实例。

Component 是一个 @Component 修饰的接口,它定义一系列无参数方法,返回需要的类型。Dagger 会生成它的实现类,该类命名是在接口名前加 Dagger(如果你是用的Android Studio,要点编译按钮后才会生成实现类)。

@Component 注解还可以传一个参数,modules,即该 Component 所依赖的 Module

@Component(modules = DripCoffeeModule.class)
interface CoffeeShop {
  CoffeeMaker maker();
}

在应用的入口点,通过 Component 的 builder 构造 Component 的实例,需要手动创建一个 Module 的实例。

CoffeeShop coffeeShop = DaggerCoffeeShop.builder()
    .dripCoffeeModule(new DripCoffeeModule())
    .build();

总结

我们一块学习了 Dagger 中最基本的概念:

  1. @Inject 声明依赖
  2. @Provides 我们自定义如何提供一个实例
  3. @Module 修饰一个类,它内部可以定义多个 @Provides 修饰的方法
  4. @Component 修饰一个接口,它定义了依赖形成的图的一系列根。启动这个构造系统的×××。

本文主要参考了,Dagger 官方文档

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章