Dagger2实现依赖注入之深入探究

本文详细探讨了Dagger2在Android应用中的依赖注入原理。通过实例解释了Dagger2如何通过编译时生成的类如DaggerPassPortComponent、PassPortModule_ProvideIDCardFactory等来实现依赖关系,并在PassPortActivity中注入成员变量,从而理解Dagger2的注入流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上一篇文章 Dagger2实现依赖注入之一步一步带你入门已经和大家分享了Dagger2的基本使用,如果你还没学会,可以边看文章边自己操作一遍。

上次说到,第六个步骤需要我们自己去重新编译一下项目,不然是无法执行最后一步的,也就是添加以下代码。
     DaggerPassPortComponent.builder()
                    .applicationComponent(getAppComponent())
                    .passPortModule(new PassPortModule(this))
                    .build()
                    .inject(this);

我们可以看到代码中有个 DaggerPassPortComponent,这个类就是完成依赖关系后重新编译生成的,但是如果编译不过是不会生成这个类的,这里说下,如果在目标类用 @Inject 做了注解的属性但是没有相应地在提供依赖类中写明提供依赖的方法,编译也是不会过的,是不是有点绕,没事,我们看代码。

比如我在 PassPortActivity 中用 @Inject 注解了两个属性,但是我在 PassPortModule 中把 provideIDCard 方法注释掉,那么重新编译之后就会出错。
        @Inject
        IDCardBean mIDCard;

        @Inject
        FamilyRegisterBean mFamilyRegister;

    //    @PerActivity
    //    @Provides
    //    public IDCardBean provideIDCard() {
    //        return new IDCardBean(mView);
    //    }

        @PerActivity
        @Provides
        public FamilyRegisterBean provideFamilyRegister() {
            return new FamilyRegisterBean(mView);
        }







编译成功之后就会生成一个   DaggerPassPortComponent ,那么这是个什么东西呢,我们一步一步看下他的源码,点 builder() 之后看到
    public static Builder builder() {
        return new Builder();
      }

直接就 new 一个 Builder 实例,这个Builder 是他的内部类
     public static final class Builder {
        private PassPortModule passPortModule;

        private ApplicationComponent applicationComponent;

        private Builder() {}

        public PassPortComponent build() {
          if (passPortModule == null) {
            throw new IllegalStateException(PassPortModule.class.getCanonicalName() + " must be set");
          }
          if (applicationComponent == null) {
            throw new IllegalStateException(
                ApplicationComponent.class.getCanonicalName() + " must be set");
          }
          return new DaggerPassPortComponent(this);
        }

        public Builder passPortModule(PassPortModule passPortModule) {
          this.passPortModule = Preconditions.checkNotNull(passPortModule);
          return this;
        }

        public Builder applicationComponent(ApplicationComponent applicationComponent) {
          this.applicationComponent = Preconditions.checkNotNull(applicationComponent);
          return this;
        }
      }



从中也能很清楚看到,里面的 passPortModule 方法可以把你的 Module 传进去,接着再执行 build()方法,这个方法里面先是判空,然后 new 一个 DaggerPassPortComponent实例。
     private DaggerPassPortComponent(Builder builder) {
        assert builder != null;
        initialize(builder);
      }



而 initalize(builder) 中则有以下重要的代码
    this.provideIDCardProvider =
            DoubleCheck.provider(PassPortModule_ProvideIDCardFactory.create(builder.passPortModule));
     
    this.provideFamilyRegisterProvider =
            DoubleCheck.provider(PassPortModule_ProvideFamilyRegisterFactory.create(builder.passPortModule));

    this.passPortActivityMembersInjector =
            PassPortActivity_MembersInjector.create(provideIDCardProvider, provideFamilyRegisterProvider);




可以看出有一个 PassPortModule_ProvideIDCardFactory 和 PassPortModule_ProvideFamilyRegisterFactory,这两个类也是 Dagger2 生成的,点进去 create方法我们可以看到,其实这两个都是生产依赖的工厂类
    public final class PassPortModule_ProvideFamilyRegisterFactory
        implements Factory<FamilyRegisterBean> {
      private final PassPortModule module;

      public PassPortModule_ProvideFamilyRegisterFactory(PassPortModule module) {
        assert module != null;
        this.module = module;
      }

      @Override
      public FamilyRegisterBean get() {
        return Preconditions.checkNotNull(
            module.provideFamilyRegister(), "Cannot return null from a non-@Nullable @Provides method");
      }

      public static Factory<FamilyRegisterBean> create(PassPortModule module) {
        return new PassPortModule_ProvideFamilyRegisterFactory(module);
      }
    }



还有一个 passPortActivityMembersInjector ,create方法也是 new 出一个实例
    public final class PassPortActivity_MembersInjector implements MembersInjector<PassPortActivity> {
     
      private final Provider<IDCardBean> mIDCardProvider;

      private final Provider<FamilyRegisterBean> mFamilyRegisterProvider;

      public PassPortActivity_MembersInjector(
          Provider<IDCardBean> mIDCardProvider,
          Provider<FamilyRegisterBean> mFamilyRegisterProvider) {
        assert mIDCardProvider != null;
        this.mIDCardProvider = mIDCardProvider;
        assert mFamilyRegisterProvider != null;
        this.mFamilyRegisterProvider = mFamilyRegisterProvider;
      }

      public static MembersInjector<PassPortActivity> create(Provider<IDCardBean> mIDCardProvider,
                                                             Provider<FamilyRegisterBean> mFamilyRegisterProvider) {
        
          return new PassPortActivity_MembersInjector(mIDCardProvider, mFamilyRegisterProvider);
      }

      @Override
      public void injectMembers(PassPortActivity instance) {
        if (instance == null) {
          throw new NullPointerException("Cannot inject members into a null reference");
        }
        instance.mIDCard = mIDCardProvider.get();
        instance.mFamilyRegister = mFamilyRegisterProvider.get();
      }

      public static void injectMIDCard(
          PassPortActivity instance, Provider<IDCardBean> mIDCardProvider) {
        instance.mIDCard = mIDCardProvider.get();
      }

      public static void injectMFamilyRegister(
          PassPortActivity instance, Provider<FamilyRegisterBean> mFamilyRegisterProvider) {
        instance.mFamilyRegister = mFamilyRegisterProvider.get();
      }
    }



上述源码中的 provider 其实就是一个接口,里面只有一个方法 get()
    public interface Provider<T> {

        /**
         * Provides a fully-constructed and injected instance of {@code T}.
         *
         * @throws RuntimeException if the injector encounters an error while
         *  providing an instance. For example, if an injectable member on
         *  {@code T} throws an exception, the injector may wrap the exception
         *  and throw it to the caller of {@code get()}. Callers should not try
         *  to handle such exceptions as the behavior may vary across injector
         *  implementations and even different configurations of the same injector.
         */
        T get();
    }

那么在  DaggerPassPortComponent 调用 inject()方法的时候,实际就是调用  passPortActivityMembersInjector 中的  injectMembers()方法,就是在这步真正实现了依赖注入。
    @Override
      public void injectMembers(PassPortActivity instance) {
        if (instance == null) {
          throw new NullPointerException("Cannot inject members into a null reference");
        }
        instance.mIDCard = mIDCardProvider.get();
        instance.mFamilyRegister = mFamilyRegisterProvider.get();
      }



细心的朋友已经知道,mFamilyRegisterProvider.get() 实际就是  PassPortModule_ProvideFamilyRegisterFactory 中的 get()方法,里面就是你在module里面写的提供依赖的方法。
     @Override
      public FamilyRegisterBean get() {
        return Preconditions.checkNotNull(
            module.provideFamilyRegister(), "Cannot return null from a non-@Nullable @Provides method");
      }



到此为止,Dagger2的依赖注入流程就和大家分享完了,其实生成的代码都比较简单,大家可以自己再去跟一下代码,看完之后你会对Dagger2有更深的了解。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值