Dagger 注入的简单原理

1,164 阅读2分钟

最简单的使用步骤:

声明一个 Module

@Module
public class MainModule {

    @Provides
    Dog provideDog(){
        return new Dog("bob");
    }

}

声明一个 Component 表明要把哪个 module 注入到哪些对象,如下表示把 MainModule 注入到 MainActivity 对象中,那么在 MainActivity 中就可以随意使用 @Inject 注入 MainModule 中的提供的对象实例。

@Component(modules = MainModule.class)
public interface MainComponent {
    void inject(MainActivity mainActivity);
}

然后我们在 MainActivivty 中使用:

class MainActivity : AppCompatActivity() {
    @Inject
    lateinit var dog1: Dog

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        DaggerMainComponent.builder().build().inject(this)
        TextView.text = "$dog1"
    }
}

就可以不需要 new Dog() 而直接得到一个现成的实例,这背后是怎么实现的呢?一起来看看。

编译之后,dagger 注解处理器会生成 3 个文件:

  1. DaggerMainComponent
  2. MainActivity_MembersInjector
  3. MainModule_ProvideDogFactory

上文中我们注入之前需要在 MainActivity 先初始化一下 DaggerMainComponent.builder().build().inject(this) 注入到当前的类中。

DaggerMainComponent 具体实现了如何把一个 MainModule 注入到 MainActivity中。

public final class DaggerMainComponent implements MainComponent {
  private final MainModule mainModule;

  private DaggerMainComponent(MainModule mainModuleParam) {
    this.mainModule = mainModuleParam;
  }

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

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

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

  private MainActivity injectMainActivity(MainActivity instance) {
    MainActivity_MembersInjector.injectDog1(
        instance, MainModule_ProvideDogFactory.provideDog(mainModule));
    return instance;
  }

  public static final class Builder {
    private MainModule mainModule;

    private Builder() {}

    public Builder mainModule(MainModule mainModule) {
      this.mainModule = Preconditions.checkNotNull(mainModule);
      return this;
    }

    public MainComponent build() {
      if (mainModule == null) {
        this.mainModule = new MainModule();
      }
      return new DaggerMainComponent(mainModule);
    }
  }
}

首先 DaggerMainComponent.Builder 的 build 方法中会先创建一个 MainModule 实例,然后传入 DaggerMainComponent。

然后再看看 inject(),内部通过 MainActivity_MembersInjector.injectDog1(MainActivity,Dog) 实现,这里的 dog 实例是从 MainModule_ProvideDogFactory.provideDog(mainModule) 这个工厂类获得的。

public final class MainModule_ProvideDogFactory implements Factory<Dog> {
  private final MainModule module;

  public MainModule_ProvideDogFactory(MainModule module) {
    this.module = module;
  }

  @Override
  public Dog get() {
    return provideDog(module);
  }

  public static MainModule_ProvideDogFactory create(MainModule module) {
    return new MainModule_ProvideDogFactory(module);
  }

  public static Dog provideDog(MainModule instance) {
    return Preconditions.checkNotNull(
        instance.provideDog(), "Cannot return null from a non-@Nullable @Provides method");
  }
}

provideDog() 这个方法很简单,就是判断下实例是必须不能为空。

最后通过 injectDog1()MainActivitydog1 赋值,完成了注入过程。

  public static void injectDog1(MainActivity instance, Dog dog1) {
    instance.dog1 = dog1;
  }

这样一个注入过程就完成了,是不是很简单。