美文网首页
Dagger2 | 一、入门 - @Inject

Dagger2 | 一、入门 - @Inject

作者: mrzhqiang | 来源:发表于2020-06-21 18:10 被阅读0次

Dagger2 是由谷歌开源的依赖注入框架,主要用于 Java 以及 Android 的依赖管理。
它是在编译期间完成依赖的注入,性能和效率都非常高,不会产生额外的负担。

1.1 前提条件

  • Android Studio:建议使用最新 4.0 版本,体验飞一般的开发速度
  • Android Application:通过 Android Studio 创建的 Empty Activity 工程
  • Dagger2 Dependencies:富有冒险精神的开发者通常使用当前最新版本——2.28

1.1.1 Android Studio

尽管是谷歌家推出的 IDE,但还是喜欢 JetBrains 系列全家桶。
所以先下载一个工具箱,然后通过它管理 Android Studio 版本的升降级。
下载地址:https://www.jetbrains.com/toolbox-app/

工具箱界面:

Toolbox App

1.1.2 Android Application

执行步骤(二选一):

  1. 打开全新的 Android Studio >> Start a new Android Studio project >> 按照下图选择 >> Next
  2. 从已打开的 Android Studio >> New >>> New Project >>> 按照下图选择 >> Next

Next 之后:

  • 输入 Name 即应用名称
  • 输入 Package name 即包名
  • 选择 Language 即开发语言
  • 选择 Minimum SDK 即系统 API 版本
  • 点击 Finish 即完成项目的创建

1.1.3 Dagger2 Dependencies

点击右边的链接,可以查看 Dagger2 依赖的相关信息:Dagger2 For Maven Center

1.2 由浅入深

本节内容仅涉及 @Inject 的最简单使用,由浅入深才能掌握精髓。

1.2.1 添加依赖

打开 app 模块的 build.gradle 文件,添加如下内容:

// Add Dagger dependencies
dependencies {
  // other dependencies

  api 'com.google.dagger:dagger:2.28'
  annotationProcessor 'com.google.dagger:dagger-compiler:2.28'
}

随后 Sync Now 一下,完成依赖的自动下载。

Dagger2 的结构

1.2.2 构造注入

现在我们创建一个最简单的 Account 类:

import javax.inject.Inject;

public class Account {
  public String username;
  public String password;

  @Inject
  public Account() {
  }
}

解释:关于 @Inject 注解,这是 JSR330 的特性,即标记注入实例,用在构造函数、方法和字段上。

JSR330 的结构

1.2.3 实例工厂类

使用 Ctrl + F9 编译后,在 app\build\generated\ap_generated_sources\debug\out 目录下可以找到编译出来的类文件。

编译后的依赖类

它的内容如下:

import dagger.internal.Factory;

@SuppressWarnings({
    "unchecked",
    "rawtypes"
})
public final class Account_Factory implements Factory<Account> {
  @Override
  public Account get() {
    return newInstance();
  }

  public static Account_Factory create() {
    return InstanceHolder.INSTANCE;
  }

  public static Account newInstance() {
    return new Account();
  }

  private static final class InstanceHolder {
    private static final Account_Factory INSTANCE = new Account_Factory();
  }
}

这就是一个简单的 单例模式 + 工厂模式 的实例工厂类。

1.2.4 依赖注入

我们在 MainActivity 中注入 Account 试试:

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
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);
  }
}

不同于 Spring FrameworkIoC 容器,对于实例字段来说, Dagger2 只能在非 private 级别上进行注入,除非你在构造函数或者方法上进行注入,才可以将字段声明为 private 的可见性,但对于 AndroidActivity,实例由系统创建,不适合构造函数的注入方式,所以这里声明为默认级别的可见性。

1.2.5 成员注入器

继续查看编译后的文件夹:

编译后的注入类

内容如下:

import dagger.MembersInjector;
import dagger.internal.InjectedFieldSignature;
import javax.inject.Provider;

@SuppressWarnings({
    "unchecked",
    "rawtypes"
})
public final class MainActivity_MembersInjector implements MembersInjector<MainActivity> {
  private final Provider<Account> accountProvider;

  public MainActivity_MembersInjector(Provider<Account> accountProvider) {
    this.accountProvider = accountProvider;
  }

  public static MembersInjector<MainActivity> create(Provider<Account> accountProvider) {
    return new MainActivity_MembersInjector(accountProvider);}

  @Override
  public void injectMembers(MainActivity instance) {
    injectAccount(instance, accountProvider.get());
  }

  @InjectedFieldSignature("com.github.mrzhqiang.dagger2_example.MainActivity.account")
  public static void injectAccount(MainActivity instance, Account account) {
    instance.account = account;
  }
}

从命名上来看,这是一个 MainActivity 的成员注入器,它实现了成员注入接口,并且可以看到 Account 的实例有被赋值到 MainActivity 中,它是通过 Provider<T> 这个接口来提供 Account 的实例。

1.3 运行

我们通过运行来检验一下,实例是否注入成功。
首先,修改 Account 的构造函数,并重写 toString 方法:

import androidx.annotation.NonNull;
import javax.inject.Inject;

public class Account {
  public String username;
  public String password;

  @Inject
  public Account() {
    this.username = "fssd";
    this.password = "123456";
  }

  @NonNull
  @Override public String toString() {
    return "Account{" +
        "username='" + username + '\'' +
        ", password='" + password + '\'' +
        '}';
  }
}

提示:使用 Alt + Insert 快捷键,可以生成如 Getter and Setterequals and hashCodetoString 等方法。

然后,在 app\src\main\res\layout\activity_main.xml 中,添加 TextViewid,以便通过 findViewById 找到组件的实例。

  <TextView
    android:id="@+id/content_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Hello World!"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

最后,我们在 MainActivityonCreate 方法中,找到 content_text 的实例,并让它来显示 Account 的字符串内容。

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);

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

现在我们 Run 一下看看效果:

闪退异常信息

出现了意料之中的闪退现象,这说明依赖注入没有生效。

1.4 总结

@Inect 注解在实例的构造函数上时,会生成一个 实例工厂类
@Inect 注解在实例的字段上时,会生成一个 成员注入器
仅使用 @Inject 注解,依赖注入不能生效,调用实例时,还是会抛出 NPE 异常。

下一章,我们将从 Dagger2 中寻找解决办法。

相关文章

  • Dagger2

    dagger2的GitHub地址 优秀的小白入门博客 大神的dagger2详解博客 只有Inject的模式 act...

  • Dagger2

    Dagger2 @Inject Declaring Dependencies Use @Inject to ann...

  • Dagger2 | 一、入门 - @Inject

    Dagger2 是由谷歌开源的依赖注入框架,主要用于 Java 以及 Android 的依赖管理。它是在编译期间完...

  • Dagger2在SystemUI中的应用

    Dagger2注解基础 @Inject和@Component 用 @Inject 注解标注目标类中依赖类的实例对象...

  • Dagger2 中的 Qualifier

    Dagger2 中创建实例对象有两种方式: Inject 维度:通过用 Inject 注解构造函数 Module ...

  • Dagger2

    Dagger2注解 @Inject: 用来标记需要依赖的变量,以此告诉Dagger2为它提供依赖; 是用来标记构造...

  • Dagger2神器入门(四)

    前序 Dagger2神器入门(一)Dagger2神器入门(二)Dagger2神器入门(三)在上面的一系列文章中,我...

  • Dagger2使用详解

    Dagger2注解 Dagger2使用过程中我们通常接触到的注解主要包括:@Inject, @Module, @P...

  • Dagger2代码分析理解Component和Module

    Dagger2主要有如下几个核心概念: @Component @Module @Inject @Singleton...

  • dragger2新了解

    @Inject 构造器注入,@Inject标注在构造器上其实有两层意思。 ①告诉Dagger2可以使用这个构造器构...

网友评论

      本文标题:Dagger2 | 一、入门 - @Inject

      本文链接:https://www.haomeiwen.com/subject/cooyxktx.html