iis服务器助手广告广告
返回顶部
首页 > 资讯 > 移动开发 >Android依赖注入框架Dagger2的使用方法
  • 695
分享到

Android依赖注入框架Dagger2的使用方法

AndroidDagger2Android依赖注入 2023-05-19 08:05:11 695人浏览 独家记忆
摘要

目录Dagger2注入框架原理简要分析示例代码生成代码分析DaggerActivityComponent类MainActivity_MembersInjector何处真正产生了实际参

Dagger2注入框架原理简要分析

使用Dagger2需要的依赖:

implementation 'com.Google.dagger:dagger-Android:2.46'
implementation 'com.google.dagger:dagger-android-support:2.46'
annotationProcessor 'com.google.dagger:dagger-android-processor:2.46'
annotationProcessor 'com.google.dagger:dagger-compiler:2.46'

示例代码

这里先给出我的示例代码,GitHub上的demo点这里👈

MainActivity

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    @Inject
    Gson gson;
    @Inject
    Gson gson2;
    @Inject
    SWordMan swordMan;
    //@Inject
    //Car car;
    ActivityMainBinding myBinding;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        myBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        App.get(MainActivity.this).getActivityComponent().inject(this);
        onClick();
        if(gson.hashCode() == gson2.hashCode()){
            Toast.makeText(this, "Same", Toast.LENGTH_SHORT).show();
        }else{
            Toast.makeText(this, "Different", Toast.LENGTH_SHORT).show();
        }
        myBinding.btTest2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this, swordMan.fighting(), Toast.LENGTH_SHORT).show();
            }
        });
    }
    private void onClick(){
        myBinding.btTest1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this,SecondActivity.class);
                startActivity(intent);
            }
        });
    }
}

SecondActivity

public class SecondActivity extends AppCompatActivity {
    ActivitySecondBinding S_Binding;
    @Inject
    Lazy<SwordMan> swordManLazy;//实现懒加载
    SwordMan swordMan = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        S_Binding = DataBindingUtil.setContentView(this,R.layout.activity_second);
        App.get(SecondActivity.this).getActivityComponent().inject(this);
        if(swordMan == null){
            Toast.makeText(this, "暂未初始化", Toast.LENGTH_SHORT).show();
        }
        swordMan = swordManLazy.get();
        //setContentView(R.layout.activity_second);
        S_Binding.button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(SecondActivity.this, swordMan.fighting(), Toast.LENGTH_SHORT).show();
            }
        });
    }
}

App

注意App类需要在manifest清单文件中声明。

public class App extends Application {
    ActivityComponent activityComponent;
    @Override
    public void onCreate() {
        super.onCreate();
        activityComponent = 
        DaggerActivityComponent.builder().swordmanComponent(DaggerSwordmanComponent.builder().build())
                .build();
    }
    public static App get(Context context){
        return (App) context.getApplicationContext();
    }
    ActivityComponent getActivityComponent(){
        return activityComponent;
    }
}

Component类

@ApplicationScope
@Component(modules = GsonModule.class,dependencies = SwordmanComponent.class)
public interface ActivityComponent {
    void inject(MainActivity activity);
    void inject(SecondActivity activity);
}
@Component(modules = SwordmanModule.class)
public interface SwordmanComponent {
    SwordMan getSwordman();
}

Module类以及实体类

@Module
public class GsonModule {
    @ApplicationScope
    @Provides
    public Gson provideGson(){
        return new Gson();
    }
}
@Module
public class SwordmanModule {
    @Provides
    public SwordMan provideSwordman(){
        return new SwordMan();
    }
}
public class SwordMan {
    @Inject
    public SwordMan(){
    }
    public String fighting(){
        return "欲为大树,莫于草争";
    }
}

生成代码分析

Dagger2是通过注解生成中间类的方式帮我们注入依赖的,我们就来分析它生成的中间类的代码。

由于注入器是在App类中初始化的,所以我们先从App类开始看,App类中最重要的无非就是这一句:

activityComponent = 
   DaggerActivityComponent.builder().swordmanComponent(DaggerSwordmanComponent.builder().build())
                .build();

通过DaggerActivityComonent以及builder的配置生成了一个注入器接口的实现类,所以我们先看DaggerActivityComponent类

DaggerActivityComponent类

public final class DaggerActivityComponent {
  private DaggerActivityComponent() {
  }
  public static Builder builder() {
    return new Builder();
  }
  public static final class Builder {
    private GsonModule gsonModule;
    private SwordmanComponent swordmanComponent;
    private Builder() {
    }
    public Builder gsonModule(GsonModule gsonModule) {
      this.gsonModule = Preconditions.checkNotNull(gsonModule);
      return this;
    }
    public Builder swordmanComponent(SwordmanComponent swordmanComponent) {
      this.swordmanComponent = Preconditions.checkNotNull(swordmanComponent);
      return this;
    }
    public ActivityComponent build() {
      if (gsonModule == null) {
        this.gsonModule = new GsonModule();
      }
      Preconditions.checkBuilderRequirement(swordmanComponent, SwordmanComponent.class);
      return new ActivityComponentImpl(gsonModule, swordmanComponent);
    }
  }
  private static final class ActivityComponentImpl implements ActivityComponent {
    	...
    }
}

我们先来看前面有关Builder的方法,由于我们在Activity的Component注解中添加了modules和dependencies的值,所以在builder中就会生成响应的gsonModule(GsonModule gsonModule)和swordmanComponent(SwordmanComponent swordmanComponent)方法,这两个方法分别是用来设置生成的注入器中的gsonModule和swordmanComponent对象的。

通过App类中的调用的代码我们可以发现,对于注解中的modules,我们在创建注入器的时候是不需要手动添加的,但是对dependencies注解来说就需要手动添加:

DaggerActivityComponent.builder().swordmanComponent(DaggerSwordmanComponent.builder().build())
                .build();//手动添加了DaggerSwordmanComponent的注入器

builder中的Preconditions.checkNotNull()只是用来判空的,总的来说,builder这个内部类就是用来帮助构建注入器实例的。所以我们接下来就来看这个注入器实例:

  private static final class ActivityComponentImpl implements ActivityComponent {
    private final SwordmanComponent swordmanComponent;
    private final ActivityComponentImpl activityComponentImpl = this;
    private Provider<Gson> provideGsonProvider;
    private Provider<SwordMan> getSwordmanProvider;
    private ActivityComponentImpl(GsonModule gsonModuleParam,
        SwordmanComponent swordmanComponentParam) {
      this.swordmanComponent = swordmanComponentParam;
      initialize(gsonModuleParam, swordmanComponentParam);
    }
    @SuppressWarnings("unchecked")
    private void initialize(final GsonModule gsonModuleParam,
       final SwordmanComponent swordmanComponentParam) {
      this.provideGsonProvider = DoubleCheck.provider(GsonModule_ProvideGsonFactory.create(gsonModuleParam));
      this.getSwordmanProvider = new GetSwordmanProvider(swordmanComponentParam);
    }
    @Override
    public void inject(MainActivity activity) {
      injectMainActivity(activity);
    }
    @Override
    public void inject(SecondActivity activity) {
      injectSecondActivity(activity);
    }
    private MainActivity injectMainActivity(MainActivity instance) {
		...
    }
    private SecondActivity injectSecondActivity(SecondActivity instance) {
      	...
    }
    private static final class GetSwordmanProvider implements Provider<SwordMan> {
      ...
    }
  }

先不看最后一个内部类,先看注入器类ActivityComponentImpl 实现了 ActivityComponent 接口,也就是说它就是实际的注入器类,这个类的构造方法是私有的,说明只能通过构造器来构造实例。先关注它的构造方法,构造方法传入的参数正是我们在Component接口的注解中写入的值:

@Component(modules = GsonModule.class,dependencies = SwordmanComponent.class)
...
private void initialize(final GsonModule gsonModuleParam,
       final SwordmanComponent swordmanComponentParam){
       ...
       }

传入了一个GsonModule和一个SwordmanComponent,和目前这个ActivityComponent类似,这个SwordmanComponent肯定也是有一个实现类的,我们后面再看这两个类的具体内容。

接着我们接续看它的注入依赖的方法,我们在注入依赖时,显然是用到了inject方法,对应不同的注入对象,将会调用不同的inject的重载方法,我们先看MainActivity的注入方法:

private MainActivity injectMainActivity(MainActivity instance) {
      MainActivity_MembersInjector.injectGson(instance, provideGsonProvider.get());
      MainActivity_MembersInjector.injectGson2(instance, provideGsonProvider.get());
      MainActivity_MembersInjector.injectSwordMan(instance, Preconditions.checkNotNullFromComponent(swordmanComponent.getSwordman()));
      return instance;
    }

injectMainActivity中分别调用了注入的方法,很显然,就是将我们在MainActivity中标记为需要注入的变量给注入参数,我们接下来看这个MainActivity_MembersInjector中间类。

MainActivity_MembersInjector

就这个类的命名来说,它应该是具体负责成员变量注入依赖的注入器。前面说到在ActivityComponentImpl调用了它的injectGson等方法,我们来看这三个方法:

@InjectedFieldSignature("com.example.dagger2demo.activitys.MainActivity.gson")
  public static void injectGson(MainActivity instance, Gson gson) {
    instance.gson = gson;
  }
  @InjectedFieldSignature("com.example.dagger2demo.activitys.MainActivity.gson2")
  public static void injectGson2(MainActivity instance, Gson gson2) {
    instance.gson2 = gson2;
  }
  @InjectedFieldSignature("com.example.dagger2demo.activitys.MainActivity.swordMan")
  public static void injectSwordMan(MainActivity instance, SwordMan swordMan) {
    instance.swordMan = swordMan;
  }

看到这里,这三个方法的作用已经非常明显了,将我们需要注入依赖的对象传入这三个方法中,方法就会给需要注入依赖对象中标记为@Inject的成员变量赋值。至于这个@InjectedFieldSignature注解,@InjectedFieldSignature注解是Dagger中的一个自定义注解,用于帮助Dagger在运行时自动生成代码以实现依赖注入。它用于标记要进行依赖注入的字段,并提供了一个字符串参数,用于标识该字段所依赖的对象的类型。在运行时,Dagger会扫描这些注解并自动生成相应的代码,以实现将依赖注入到被标记的字段中。

何处真正产生了实际参数

这时候新的问题产生了,这些被注入的参数是在哪里被初始化的呢,换句话说,injectGson()方法中的第二个参数gson是在哪里被开辟空间的呢,答案就在之前的ActivityComponentImpl中:

 private MainActivity injectMainActivity(MainActivity instance) {
      MainActivity_MembersInjector.injectGson(instance, provideGsonProvider.get());
 		...
    }

从这里可以看出,这个实际被注入的参数是由provideGsonProvider的get方法提供的:

   @SuppressWarnings("unchecked")
    private void initialize(final GsonModule gsonModuleParam,
        final SwordmanComponent swordmanComponentParam) {
      this.provideGsonProvider = DoubleCheck.provider(GsonModule_ProvideGsonFactory.create(gsonModuleParam));
      this.getSwordmanProvider = new GetSwordmanProvider(swordmanComponentParam);
    }
	...
	public final class GsonModule_ProvideGsonFactory implements Factory<Gson> {
	  private final GsonModule module;
	  public GsonModule_ProvideGsonFactory(GsonModule module) {
	    this.module = module;
	  }
	  @Override
	  public Gson get() {
	    return provideGson(module);
	  }
	  public static GsonModule_ProvideGsonFactory create(GsonModule module) {
	    return new GsonModule_ProvideGsonFactory(module);
	  }
	  public static Gson provideGson(GsonModule instance) {
	    return Preconditions.checkNotNullFromProvides(instance.provideGson());
	  }
	}

这里DoubleCheck 是 Dagger2 中的一个工具类,用于确保依赖只被创建一次,具体来说,由于我们在注入器接口中标记了被注入参数的作用域,所以会调用DoubleCheck方法。紧接着我们看GsonModule_ProvideGsonFactory,很显然实现调用了create方法,但是create方法又是实际调用了GsonModule_ProvideGsonFactory的构造方法,这里传入了GsonModule类,还记得GsonModule类吗?正是我们自己写的实例提供者。

现在我们继续返回到ActivityComponentImpl中,看这个GsonModule的实例在哪里,答案在builder中。我们先一个一个往前捋:

首先在initialize方法中调用了create:

this.provideGsonProvider = DoubleCheck.provider(GsonModule_ProvideGsonFactory.create(gsonModuleParam))

所以我们需要看initialize方法中传入的GsonModule实例来自哪里,是来自ActivityComponentImpl的构造方法中:

private ActivityComponentImpl(GsonModule gsonModuleParam,
        SwordmanComponent swordmanComponentParam) {
      this.swordmanComponent = swordmanComponentParam;
      initialize(gsonModuleParam, swordmanComponentParam);
    }

那这个构造方法中的GsonModule来自哪里呢,之前我们提到过,由于这个构造方法是私有的,所以我们只能通过构造器builder来创建,所以答案显然是在builder这个内部类中:

    public ActivityComponent build() {
      if (gsonModule == null) {
        this.gsonModule = new GsonModule();
      }
      Preconditions.checkBuilderRequirement(swordmanComponent, SwordmanComponent.class);
      return new ActivityComponentImpl(gsonModule, swordmanComponent);
    }

这个GsonModule类的实例正是调用了我们写的GsonModule的构造方法,所以我们可以画出传递的流程图:

简要流程图(仅适用于本示例)

简而言之,Dagger2正是通过APT和生成的中间件代码来实现依赖注入的。

到此这篇关于Android依赖注入框架Dagger2的使用方法的文章就介绍到这了,更多相关Android Dagger2内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Android依赖注入框架Dagger2的使用方法

本文链接: https://www.lsjlt.com/news/212867.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Android依赖注入框架Dagger2的使用方法
    目录Dagger2注入框架原理简要分析示例代码生成代码分析DaggerActivityComponent类MainActivity_MembersInjector何处真正产生了实际参...
    99+
    2023-05-19
    Android Dagger2 Android依赖注入
  • Android ButterKnife依赖注入框架如何使用
    这篇文章主要介绍“Android ButterKnife依赖注入框架如何使用”,在日常操作中,相信很多人在Android ButterKnife依赖注入框架如何使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作...
    99+
    2023-07-05
  • android依赖注入框架怎么用
    在Android中,可以使用Dagger 2作为依赖注入框架。以下是使用Dagger 2进行依赖注入的步骤:步骤1:添加Dagger...
    99+
    2023-10-20
    android
  • ASP.NET Core依赖注入框架的使用
    目录一、IoC框架二、IoC-Autofac 三、.NET Core中自带DI的使用四、Autofac 使用五、批量注入 前言: 还记得上篇文章中ASP.NET Core 依赖注入详...
    99+
    2024-04-02
  • AndroidButterKnife依赖注入框架使用教程
    目录ButterKnife的工作原理BuffterKnife 采用 注解+ APT技术 APT:Annotation Processor tool 注解处理器,是javac的一个工具...
    99+
    2023-02-23
    Android ButterKnife依赖注入 Android ButterKnife Android依赖注入
  • spring框架依赖注入方式有哪几种
    Spring框架的依赖注入方式主要有三种:1. 构造函数注入(Constructor Injection):通过构造函数实现依赖注入...
    99+
    2023-08-08
    spring
  • 怎么在Spring框架中注入依赖
    这篇文章将为大家详细讲解有关怎么在Spring框架中注入依赖,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。三种依赖注入的方式属性注入,通过setter方法注入bean的属性值或依赖的对象 构...
    99+
    2023-05-30
    spring
  • Spring框架实现依赖注入的原理
    目录什么是依赖注入实现原理IOC容器Bean定义依赖注入构造函数注入Setter方法注入字段注入生命周期回调注解总结Spring 框架作为 Java 开发中最流行的框架之一,其核心特...
    99+
    2023-05-15
    Spring依赖注入 Spring依赖注入的方式 Spring依赖注入原理
  • 详解Laravel框架的依赖注入功能
    目录概述真实的例子结论概述 任何时候,你在一个控制器类中请求一个依赖,这个服务容器负责: 1.自动地在构造函数中检测依赖关系 2.如果需要构建这个依赖关系 3.通过构造函数创建对象形...
    99+
    2024-04-02
  • Asp.net core程序中使用微软的依赖注入框架
    我之前在博文中介绍过Asp.net core下系统自带的依赖注入框架,这个依赖框架在Microsoft.Extensions.DependencyInjection中实现,本身并不是...
    99+
    2024-04-02
  • Asp.net core程序中怎么使用微软的依赖注入框架
    本篇内容主要讲解“Asp.net core程序中怎么使用微软的依赖注入框架”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Asp.net core程序中怎么使用微软的依赖注入框...
    99+
    2023-07-02
  • Spring框架实现依赖注入的原理是什么
    这篇文章主要介绍“Spring框架实现依赖注入的原理是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Spring框架实现依赖注入的原理是什么”文章能帮助大家解决问题。Spring 框架作为 Ja...
    99+
    2023-07-06
  • ASP.NETCore使用AutoFac依赖注入
    实现代码新建接口类:IRepository.cs,规范各个操作类的都有那些方法,方便管理。using System;using System.Collections.Generic;using System.L...
    99+
    2023-06-03
  • Laravel框架中依赖注入功能的示例分析
    这篇文章将为大家详细讲解有关Laravel框架中依赖注入功能的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。概述任何时候,你在一个控制器类中请求一个依赖,这个服务容器负责:自动地在构造函数中检测依...
    99+
    2023-06-15
  • android依赖注入的实现方式是什么
    Android中依赖注入的实现方式有以下几种:1. 构造函数注入:通过在类的构造函数中传入依赖对象的实例来实现注入。这种方式最为简单...
    99+
    2023-10-09
    android
  • AndroidHilt依赖注入的使用讲解
    目录什么是依赖注入使用依赖注入的好处Hilt中常用的预定义限定符@HiltAndroidApp@AndroidEntryPoint@Module@InstallIn@Provides...
    99+
    2023-01-16
    Android Hilt依赖注入 Android Hilt Android依赖注入
  • mybatisTypeHandler注入spring的依赖方式
    目录TypeHandler注入spring的依赖解决方法mybatis扩展:自定义TypeHandler1、编写自定义TypeHandler2、配置TypeHandler3、测试4、...
    99+
    2024-04-02
  • laravel依赖注入怎么使用
    Laravel的依赖注入是一种通过自动解析和解决类之间的依赖关系的机制。下面是在Laravel中使用依赖注入的步骤:1. 声明依赖关...
    99+
    2023-09-21
    laravel
  • Spring依赖注入怎么使用
    Spring是一个开源的Java框架,提供了一个容器来管理应用程序的组件并实现了依赖注入(Dependency Injection)...
    99+
    2023-09-26
    Spring
  • Spring使用Setter完成依赖注入方式
    目录对依赖注入的理解使用Setter完成不同类型属性的注入整体配置文件Spring解决setter方式的循环依赖的原理对依赖注入的理解 依赖:实体间的所有依赖由容器创建 注入:容器负...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作