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

Dagger2实现原理分析 Dagger是一个依赖注入框架,这个框架往往给人一种“高端,但是却很难用“的感觉。我们在使用或者阅读别人的项目时,往往会陷入dagger搭建的”迷宫里”绕不出来。导致Dagger被认为是android史上”最受冷落的优质库”。本文先通过理清依赖注入的概念,然后详细介绍Dagger一些常见的使用场景和注意事项,最后介绍一下Dagger主要功能实现的原理。帮助大家进行理解。 阅读详情
上一篇文章 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有更深的了解。



FPGA波束形成:从算法到硬件的艺术之旅 本文深入探讨了FPGA在波束形成技术中的应用,从算法原理到Verilog硬件实现的全过程。文章详细分析了FPGA并行处理、低延迟和可重构特性如何优化波束形成系统性能,并提供了Verilog关键模块代码示例和资源优化策略,为工程师实现高效FPGA波束形成解决方案提供实用指导。 阅读详情

相关推荐

保姆级教程:用torch.profiler给你的vLLM推理做个“全身体检”(附Perfetto可视化分析)

本文提供了一份详细的vLLM推理性能分析教程,通过torch.profiler和Perfetto工具链实现从数据采集到可视化分析的全流程。文章涵盖了环境配置、性能数据采集、trace文件解析以及Perfetto可视化分析,帮助开发者优化大模型推理服务的性能,显著降低计算资源消耗。

weixin_29041767的博客 357

Dagger2详解-从代码分析其原理

Dagger2基本概念请移步官方文档,或者我的翻译。架构方面请关注GitHub(MVP+Retrofit+Dagger2+Okhttp)及我的文章Android UI框架快速搭建实践Dagger2是Dagger1的分支,由谷歌公司接手开发,目前的版本是2.0。Dagger2解决问题的基本思想是:利用生成和写的代码混合达到看似所有的产生和提供依赖的代码都是手写的样子。如果我们将Dagger2和1比较...

371

AD9826的时序分析及Verliog代码

AD9826的时序分析及Verliog代码 (本文对AD9826的模式和时序进行了分析,如有错误敬请指正,关于这款ADC芯片的基本参数,本文不做过多介绍) 1、AD9826的模式 AD9826的采样模式主要有两种,一种是“CDS模式”,一种是“SHA模式”;在这两种模式下分别有1通道、2通道、3通道的采样模式 (1)CDS模式 简单的来说CDS模式就是,有两个采样时钟,一个是ADCCLK1,用来采样CCD波形的参考电平,一个是ADCCLK2用来采样数据电平,然后经过,偏移量调节,再经过PGA增益放大最

m0_50102488的博客 6473

终极TensorFlow 2.3教程:从零开始快速掌握深度学习全栈技能

TensorFlow-Course是一个革命性的开源教程项目,专为想要快速掌握TensorFlow 2.3全栈技能的初学者和普通用户设计。这个项目提供了简单易用、随时可用的TensorFlow教程,帮助用户从基础概念到高级应用全面掌握深度学习框架。无论你是机器学习新手还是有经验的开发者,这个教程都能让你快速上手TensorFlow 2.3,构建强大的深度学习模型。🎯 ## 📊 为什么选择Te

gitblog_00070的博客 452

保姆级教程:用Python+OpenCV搞定Orbbec Gemini深度与彩色流对齐(附完整代码)

本文提供了一份详细的Orbbec Gemini深度与彩色流对齐教程,涵盖从环境配置到完整代码实现的每一步。通过解析深度流对齐原理,对比不同对齐模式,并提供工业级应用中的问题排查方法,帮助开发者快速掌握Orbbec Gemini相机的使用技巧。文章还包含进阶应用如点云生成与三维重建的实战代码。

weixin_29090917的博客 470

Exchange 2013/2016/2019修改附件大小限制

Exchange 2013/2016/2019邮件大小限制 可以在三个位置上配置Exchange上的默认邮件大小限制: 组织传输设置 发送/接收连接器设置 用户邮箱设置 1.打开Exchange Management Shell 使用命令查看默认限制 get-transportconfig | ft maxsendsize, maxreceivesize get-receiveconnector | ft name, maxmessagesize get-sendconnector | ft

高级基础架构专家-Hunter 6098

Nest.js 实战系列第二篇-实现注册、扫码登陆、jwt认证等

大厂技术高级前端Node进阶点击上方程序员成长指北,关注公众号回复1,加入高级Node交流群大家好我是考拉????,这是Nest.js 实战系列第二篇,我要用最真实的场景让你学会使用...

程序员成长指北 8439

Gemini Enterprise免费试用攻略:解锁企业级AI平台的隐藏技巧与避坑指南

本文详细介绍了Gemini Enterprise免费试用的全流程攻略,包括注册优化、团队协作、资源管理和典型应用场景。通过解锁企业级AI平台的核心功能如Gemini 3.0 Pro模型和Nano Banana图像生成系统,帮助企业高效评估AI与业务的契合度。文章还提供了安全合规与数据管理的实用建议,确保试用过程顺畅无忧。

weixin_29233857的博客 657

Dagger2解析(实例+源码)

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

weixin_34205076的博客 276

PreScan快速入门到精通第二十一讲驾驶员模型之驾驶员在环

请注意,操纵杆的输出角度是以度为单位的,而方向盘执行器希望其输入是以弧度为单位的。当选择一个支持的方向盘时,PreScan会自动将按钮映射到正确的功能上(如换挡),并设置轴的正确范围(如转向角度)。该系统中的所有其他组件都是为了提供正确的按钮映射,并为所选的方向盘设置正确的范围。对于每一个额外连接的控制器,它们的ID会增加一个,例如第二个控制器的设备ID为1,第三个控制器的设备ID为2,等等。由于所有的方向盘最初放在编译表上的设备ID都是0,所以用户应该先进行正确的调整,将每个控制器设置为正确的设备ID。.

小明师兄的博客 1423

使用DrissionPage和自动化技术实现得物鞋子信息爬取

本文介绍了一个基于DrissionPage技术的得物鞋子信息采集系统,能自动化采集商品图片、价格等数据并保存为Excel。系统采用浏览器模拟技术处理动态加载内容,通过XPath定位元素,实现智能交互和完整数据采集。关键技术包括:图片URL提取与下载、Excel数据集成与图片嵌入、文件名安全处理等。项目适用于市场分析和学术研究,强调必须遵守法律法规和平台规则,仅用于非商业用途。与API爬虫相比,浏览器自动化能更好处理现代Web应用,但需注意知识产权保护。

那些看似不起波澜的日复一日,会在某天让你看到坚持的意义 1665

node.js 中间件_Node.js中的Passport中间件(模块)

node.js 中间件Hi! Welcome to Node.js Authentication Series, where we'll study and program the passport module or middleware. 嗨! 欢迎使用Node.js身份验证系列 ,我们将在其中研究和编程通行证模块或中间件 。 Nowadays, an important tool in ...

cumt951045的博客 553

10、数据挖掘与轨迹生成技术:FSSEMiner与CondTraj - GAN的探索

本文介绍了两种先进的数据处理技术:FSSEMiner算法用于从动态属性图中挖掘频繁顺序子图演化模式,揭示如交通流和疾病传播等复杂系统的演化规律;CondTraj-GAN是一种端到端的条件生成对抗网络,能够生成高质量的合成车辆轨迹,解决真实轨迹数据因隐私问题难以获取的挑战。通过实验评估与真实数据集验证,两种技术在可扩展性、实用性及生成质量方面均表现出色,并在交通管理、城市规划、自动驾驶研发等领域具有广泛应用前景。

grafana8visual的博客 87

Dagger2的介绍和配置

前言 Dagger2的介绍和配置 Dagger2基础的使用 Dagger2进阶-编译生成源码解读 Dagger2进阶-范围的控制(Scope和Singleton) Dagger2进阶-Scope的源码探究 项目源码传送门​​​​​​​ Dagge...

木木baby的博客 1068

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Dagger2——DI依赖注入——IOC原则的实现者

《如何获得完全松耦合的程序设计》 IoC原则、DIP原则、DI设计模式可以帮助我们获得完全松耦合的程序设计。而Dagger2则是实现了依赖注入(DI)设计模式的框架,也就是它实现了IoC原则。 简而言之,Dagger2在遵循IoC原则下帮助我们创建依赖对象。我大概讲一下DI设计模式:比说A类依赖B类,那么我们通过在A类外面创建B类的对象,再将其注入A类。需要有个第三方帮我们把这件事做了(IoC的体现),那么Dagger2就是这个第三方。 Dagger2是基于java规范要求,使用注解的方式生成代码。我们通过

weixin_40763897的博客 2107

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

一文看懂依赖注入(Dagger2)

一句话解释依赖注入(DI)的作用,就是。

weixin_51020083的博客 983

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Android _ 从 Dagger2 到 Hilt 玩转依赖注入(一)

子组件是继承并扩展父组件的对象图的组件,子组件中的对象就可以依赖于父组件中提供的对象,但是父组件不能依赖于子组件依赖的对象(简单的包含关系,对吧?我们继续通过一个简单的例子来展开:假设我们有一个登录模块 LoginActivity,它依赖于 LoginModel。我们的需求是定义一个子组件,它的声明周期只在一次登录流程中存在。在。

2401_84009317的博客 830

你还停留在使用Dagger2吗? 带你一步一步走进Dagger2的世界

Dagger2是一个依赖注入框架 1.什么是依赖注入? 就是目标类中所依赖的其他的类的初始化过程,不是通过手动编码的方式创建 将其他的类初始化好的实例自动注入到我们的目标类当中。它也是面向对象的一种设计模式, 主要作用就是降低我们程序的耦合。 讲述两个场景来描述一下Dagger2: 1.在一个对象里创建另一个对象的实例。这种行为就会产生耦合现象。导致代码难以维护。 2.Picasso...

wk_先森的博客 2万+

如何用Dagger 2在Kotlin Android应用中实现依赖注入:基于PhotoAffix的完整教程

PhotoAffix 是一款用 Kotlin 编写的 Android 照片拼接应用,它将 Dagger 2 依赖注入框架运用得恰到好处:通过 1 个 AppComponent 和 5 个 Module,把图片引擎、用户偏好、协程调度器等依赖自动装配到界面层。这篇完整教程带你从核心概念到实战源码,快速掌握 Dagger 2 依赖注入的全部用法。 [![PhotoAffix Android 照片拼接

gitblog_00726的博客 971

dagger2实现原理

首先,我们定义 AppComponent 和 AppModule。Java6}79@Module15 }16}这里,@Component注解定义了一个组件,并指定了模块。@Module注解定义了一个模块,@Provides注解则指定了如何提供 MyService 实例。

VitorLiu的博客 1320

用 Dagger 2 实现依赖注入

Dagger 2 为你解析这些依赖,并生成把它们绑定在一起的代码。也有很多其它的 Java 依赖注入框架,但它们中大多数是有缺陷的,比如依赖 XML,需要在运行时验证依赖,或者在起始时造成性能负担。 Dagger 2 纯粹依赖于 Java 注解解析器以及编译时检查来分析并验证依赖。它被认为是目前最高效的依赖注入框架之一。

Treasure 287

Dagger2 依赖注入的原理分析

Dagger2 依赖注入的原理分析 因为 Dagger2 的使用情况很多,这里只对基本的使用方法进行分析。 以一个简单依赖注入举例如下: 创建 Watch 类如下: public class Watch { public Watch() { } public String work() { return "work"; } } 创建 Watc...

okclouderx的博客 451

Andriod Dagger2依赖注入

Android Dagger前言:学习Dagger首先要了解什么是依赖注入(Dependency Injection),为什么需要依赖注入,了解这些以后就可以进入Dagger的学习,现在大部分的项目都在使用Dagger2,我们先就Dagger2进行学习,慢慢了解注入的机制。what and why(Dependency Injection)what:依赖注入(DI):就好比一个人去淘宝买一件衣服,他

L_bsSua的博客 441

使用Dagger 2进行依赖注入

转: 使用Dagger 2进行依赖注入 使用Dagger 2进行依赖注入 发表于 2015-08-06   |   分类于 Android   |   8条评论 0. 前言 Dagger2是首个使用生成代码实现完整依赖注入的框架,极大减少了使用者的编码负担, 本文主要介绍如何使用Dagger2进行依赖注入。如果你不还不了解依赖注入,请看这一篇。

wxx614817的专栏 535

android dagger2 讲解,用Dagger2在Android中实现依赖注入

依赖注入这个模式(模式已经用烂了,这里再烂一次)是用来给应用的各部分解耦的。使应用开发更加可扩展,更容易维护。通过本文你会学到如何使用Dagger2来处理依赖。简介如果以对象需要另外的一个对象才能完成一个完整功能的话,那么这里就存在一个依赖。比如,悟空要用金箍棒才能三打白骨精,要筋斗云才能十万八千里。悟空有对金箍棒和筋斗云的依赖。你可以在悟空对象里初始化金箍棒,也可以用一个工厂方法批量生产金箍棒。...

weixin_30877689的博客 368

依赖注入框架Dagger2

什么的依赖注入 在软件工程中,依赖注入是实现控制反转的方式之一。百度百科中对于控制反转的解释如下:控制反转(Inversion of Control,英文缩写为IoC)把创建对象的权利交给框架。我们可以举例来说明一下,在开发中我们经常有类组合的情况,例如Student类中引用了School类,用于描述学生的学校信息,那么这就是典型的组合,再具体点的例子:假设我们的网络请求类RetrofitMan...

李锦锋 532
上一篇: Dagger2实现依赖注入之一步一步带你入门
Interface_l
博客等级 码龄12年 0粉丝 6原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值