Dagger2 | 二、入门 - @Component

2020-06-21  本文已影响0人  mrzhqiang

在上一章,依赖注入以失败告终,因为我们偏爱 @Inject,以为它可以独当一面。
可惜事与愿违,我们只好求助于 Dagger2,它推荐了一个叫 @Component 的注解。

2.1 组件注解

我们来看看这个 @Component 注解的用途。

2.1.1 创建接口

根据 API 描述,我们创建名为 ActivityComponent 的接口:

import dagger.Component;

@Component
interface ActivityComponent {
}

我们编译一下,看看结果。

Component 编译结果

出现了!一个叫 DaggerActivityComponent 的类,看看它的内容:

@SuppressWarnings({
    "unchecked",
    "rawtypes"
})
final class DaggerActivityComponent implements ActivityComponent {
  private DaggerActivityComponent() {

  }

  public static Builder builder() {
    return new Builder();
  }

  public static ActivityComponent create() {
    return new Builder().build();
  }

  static final class Builder {
    private Builder() {
    }

    public ActivityComponent build() {
      return new DaggerActivityComponent();
    }
  }
}

好像也没什么特别,就是一个普通的建造者模式。

2.1.2 注入方法

我们来写一个 inject 的接口方法:

import dagger.Component;

@Component
interface ActivityComponent {
  void inject(MainActivity activity);
}

查看编译后的内容:

@SuppressWarnings({
    "unchecked",
    "rawtypes"
})
final class DaggerActivityComponent implements ActivityComponent {
  private DaggerActivityComponent() {

  }

  public static Builder builder() {
    return new Builder();
  }

  public static ActivityComponent create() {
    return new Builder().build();
  }

  @Override
  public void inject(MainActivity activity) {
    injectMainActivity(activity);}

  private MainActivity injectMainActivity(MainActivity instance) {
    MainActivity_MembersInjector.injectAccount(instance, new Account());
    return instance;
  }

  static final class Builder {
    private Builder() {
    }

    public ActivityComponent build() {
      return new DaggerActivityComponent();
    }
  }
}

发生了什么?为什么注入器也出现了?
难道组件注入的实例,如果这个实例包含 @Inject 属性,就会被注入器发现,然后直接 new 出来?
那实例工厂又有什么用呢?为什么它不参与注入过程?

我们来取消掉 Account 构造方法上的 @Inject 注解,看看会出现什么情况:

编译无法通过

属性和构造方法都必须打上 @Inject 的标记,才能让 Dagger2 注意到这个类。

2.1.3 注入实例

现在参照 DaggerActivityComponent 的建造者设计,让我们把依赖注入到 MainActivity 中:

import android.os.Bundle;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import javax.inject.Inject;

public class MainActivity extends AppCompatActivity {

  @Inject
  Account account;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    DaggerActivityComponent.builder().build().inject(this);

    TextView contentText = findViewById(R.id.content_text);
    contentText.setText(account.toString());
  }
}

也可以利用工厂模式,简写为:

DaggerActivityComponent.create().inject(this);

2.2 运行

现在运行一下看看效果:

简单实践的运行图

2.3 总结

在接口上标记 @Component,使用方法参数指定目标类,可以生成 Dagger2 的成员注入。
随后在目标类中,创建名为 DaggerXXXXComponent 的实例,通过它来调用成员方法注入实例。
这就是最简单的 Dagger2 依赖注入流程,学会了这一招,你就已经入门。

下一章,我们讨论不能标记 @Inject 的第三方库,如何来实现依赖注入。

上一篇 下一篇

猜你喜欢

热点阅读