如何在Android项目中从头开始设置DAGGER依赖注入?

2023-11-24

如何使用匕首?如何配置 Dagger 在我的 Android 项目中工作?

我想在我的 Android 项目中使用 Dagger,但我发现它很混乱。

编辑:Dagger2 也于 2015 年 04 月 15 日发布,而且更令人困惑!

[这个问题是一个“存根”,随着我对 Dagger1 和 Dagger2 的了解更多,我将其添加到我的答案中。这个问题更多的是一个guide而不是“问题”。]


指南匕首2.x (修订版6):

步骤如下:

1.) add Dagger给你的build.gradle files:

  • 顶层构建.gradle:

.

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.0'
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' //added apt for source code generation
    }
}

allprojects {
    repositories {
        jcenter()
    }
}
  • 应用程序级别构建.gradle:

.

apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt' //needed for source code generation

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.2"

    defaultConfig {
        applicationId "your.app.id"
        minSdkVersion 14
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        debug {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    apt 'com.google.dagger:dagger-compiler:2.7' //needed for source code generation
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:24.2.1'
    compile 'com.google.dagger:dagger:2.7' //dagger itself
    provided 'org.glassfish:javax.annotation:10.0-b28' //needed to resolve compilation errors, thanks to tutplus.org for finding the dependency
}

2.)创建您的AppContextModule提供依赖项的类。

@Module //a module could also include other modules
public class AppContextModule {
    private final CustomApplication application;

    public AppContextModule(CustomApplication application) {
        this.application = application;
    }

    @Provides
    public CustomApplication application() {
        return this.application;
    }

    @Provides 
    public Context applicationContext() {
        return this.application;
    }

    @Provides
    public LocationManager locationService(Context context) {
        return (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
    }
}

3.)创建AppContextComponent提供接口来获取可注入类的类。

public interface AppContextComponent {
    CustomApplication application(); //provision method
    Context applicationContext(); //provision method
    LocationManager locationManager(); //provision method
}

3.1.)这是创建带有实现的模块的方法:

@Module //this is to show that you can include modules to one another
public class AnotherModule {
    @Provides
    @Singleton
    public AnotherClass anotherClass() {
        return new AnotherClassImpl();
    }
}

@Module(includes=AnotherModule.class) //this is to show that you can include modules to one another
public class OtherModule {
    @Provides
    @Singleton
    public OtherClass otherClass(AnotherClass anotherClass) {
        return new OtherClassImpl(anotherClass);
    }
}

public interface AnotherComponent {
    AnotherClass anotherClass();
}

public interface OtherComponent extends AnotherComponent {
    OtherClass otherClass();
}

@Component(modules={OtherModule.class})
@Singleton
public interface ApplicationComponent extends OtherComponent {
    void inject(MainActivity mainActivity);
}

Beware:: 您需要提供@Scope注释(如@Singleton or @ActivityScope)在模块的@Provides带注释的方法来在生成的组件中获取作用域提供程序,否则它将被取消作用域,并且每次注入时都会获得一个新实例。

3.2.)创建一个应用程序范围的组件,指定您可以注入的内容(这与injects={MainActivity.class}在 Dagger 1.x 中):

@Singleton
@Component(module={AppContextModule.class}) //this is where you would add additional modules, and a dependency if you want to subscope
public interface ApplicationComponent extends AppContextComponent { //extend to have the provision methods
    void inject(MainActivity mainActivity);
}

3.3.)对于您的依赖项can自己通过构造函数创建,并且不想使用重新定义@Module(例如,您使用构建风格来更改实现类型),您可以使用@Inject带注释的构造函数。

public class Something {
    OtherThing otherThing;

    @Inject
    public Something(OtherThing otherThing) {
        this.otherThing = otherThing;
    }
}

另外,如果您使用@Inject构造函数,您可以使用字段注入而无需显式调用component.inject(this):

public class Something {
    @Inject
    OtherThing otherThing;

    @Inject
    public Something() {
    }
}

These @Inject构造函数类会自动添加到相同范围的组件中,而无需在模块中显式指定它们。

A @Singleton scoped @Inject构造函数类将出现在@Singleton作用域组件。

@Singleton // scoping
public class Something {
    OtherThing otherThing;

    @Inject
    public Something(OtherThing otherThing) {
        this.otherThing = otherThing;
    }
}

3.4.)在为给定接口定义特定实现后,如下所示:

public interface Something {
    void doSomething();
}

@Singleton
public class SomethingImpl {
    @Inject
    AnotherThing anotherThing;

    @Inject
    public SomethingImpl() {
    }
}

您需要使用以下命令将特定实现“绑定”到接口@Module.

@Module
public class SomethingModule {
    @Provides
    Something something(SomethingImpl something) {
        return something;
    }
}

自 Dagger 2.4 以来的简写如下:

@Module
public abstract class SomethingModule {
    @Binds
    abstract Something something(SomethingImpl something);
}

4.)创建一个Injector类来处理您的应用程序级组件(它取代了整体ObjectGraph)

(note: Rebuild Project来创建DaggerApplicationComponent使用 APT 的构建器类)

public enum Injector {
    INSTANCE;

    ApplicationComponent applicationComponent;

    private Injector(){
    }

    static void initialize(CustomApplication customApplication) {
        ApplicationComponent applicationComponent = DaggerApplicationComponent.builder()
           .appContextModule(new AppContextModule(customApplication))
           .build();
        INSTANCE.applicationComponent = applicationComponent;
    }

    public static ApplicationComponent get() {
        return INSTANCE.applicationComponent;
    }
}

5.)创造你的CustomApplication class

public class CustomApplication
        extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        Injector.initialize(this);
    }
}

6.) add CustomApplication给你的AndroidManifest.xml.

<application
    android:name=".CustomApplication"
    ...

7.)将您的课程注入MainActivity

public class MainActivity
        extends AppCompatActivity {
    @Inject
    CustomApplication customApplication;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Injector.get().inject(this);
        //customApplication is injected from component
    }
}

8.) Enjoy!

+1.)您可以指定Scope对于您可以用来创建的组件活动级作用域组件。子范围允许您提供仅针对给定子范围而不是整个应用程序所需的依赖项。通常,每个活动都会通过此设置获得自己的模块。请注意,存在范围内的提供商每个组件,这意味着为了保留该活动的实例,组件本身必须能够承受配置更改。例如,它可以通过onRetainCustomNonConfigurationInstance(),或迫击炮瞄准镜。

有关子范围的更多信息,请查看谷歌的指南。另请参阅本网站有关提供方法还有组件依赖部分) and here.

要创建自定义范围,您必须指定范围限定符注释:

@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface YourCustomScope {
}

要创建子范围,您需要在组件上指定范围,并指定ApplicationComponent作为它的依赖。显然,您还需要在模块提供程序方法上指定子范围。

@YourCustomScope
@Component(dependencies = {ApplicationComponent.class}, modules = {CustomScopeModule.class})
public interface YourCustomScopedComponent
        extends ApplicationComponent {
    CustomScopeClass customScopeClass();

    void inject(YourScopedClass scopedClass);
}

And

@Module
public class CustomScopeModule {
    @Provides
    @YourCustomScope
    public CustomScopeClass customScopeClass() {
        return new CustomScopeClassImpl();
    }
}

请注意,仅one作用域组件可以指定为依赖项。就像 Java 中不支持多重继承一样。

+2.) About @Subcomponent: 本质上是一个范围@Subcomponent可以替换组件依赖项;但您需要使用组件工厂方法,而不是使用注释处理器提供的构建器。

So this:

@Singleton
@Component
public interface ApplicationComponent {
}

@YourCustomScope
@Component(dependencies = {ApplicationComponent.class}, modules = {CustomScopeModule.class})
public interface YourCustomScopedComponent
        extends ApplicationComponent {
    CustomScopeClass customScopeClass();

    void inject(YourScopedClass scopedClass);
}

就变成这样了:

@Singleton
@Component
public interface ApplicationComponent {
    YourCustomScopedComponent newYourCustomScopedComponent(CustomScopeModule customScopeModule);
}

@Subcomponent(modules={CustomScopeModule.class})
@YourCustomScope
public interface YourCustomScopedComponent {
    CustomScopeClass customScopeClass();
}

和这个:

DaggerYourCustomScopedComponent.builder()
      .applicationComponent(Injector.get())
      .customScopeModule(new CustomScopeModule())
      .build();

就变成这样了:

Injector.INSTANCE.newYourCustomScopedComponent(new CustomScopeModule());

+3.):请检查有关 Dagger2 的其他 Stack Overflow 问题,它们提供了很多信息。例如,我当前的 Dagger2 结构指定为这个答案.

Thanks

感谢您的指导Github, TutsPlus, 乔·斯蒂尔, 弗罗格MCS and Google.

也为了这个我在写完这篇文章后找到了分步迁移指南。

And for 范围解释由基里尔.

更多信息请参见官方文档.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在Android项目中从头开始设置DAGGER依赖注入? 的相关文章

随机推荐

  • Spark.read.csv() 是一个关于转换的操作吗

    Bill在 Spark权威指南 一书中说 阅读是一种转变 而且是一种狭义的转变 现在 如果我运行下面的 Spark 代码并尝试查看 Spark UI 我会看到创建的作业df spark read csv path to file 现在根据我
  • 如何防止打字时使用空格?

    我有一个文本字段用于输入一些序列号代码 我想设置此代码在有人使用 spase 时显示警报 这意味着不允许使用空格 只允许使用减号来分隔此代码 您有解决这个问题的想法吗 我可以使用jquery验证吗 the correct typing 13
  • 哪个 IOC 容器以中等信任度运行

    您好 我正在尝试运行一个使用 Mosso 运行的网站 该网站将温莎城堡作为我的 IOC 但是我收到以下错误 SecurityException That assembly does not allow partially trusted c
  • 如何增加 R 箱线图中箱线的粗细?

    如何使用基本 R 图或箱线图函数增加箱线图 箱 部分轮廓线的粗细 也就是说 如何加粗定义分位数的框线 对于这样的情节 boxplot rnorm 100 50 10 horizontal TRUE notch TRUE 我想我需要包括一个p
  • Python 2 和 Python 3 中 zip() 函数的区别[重复]

    这个问题在这里已经有答案了 我想知道两者之间有什么区别zip python 2和python 3中的函数是 我在使用时注意到timeit这两个函数的模块表明 python 3 函数要快得多 预先非常感谢 Python 2 和 Python
  • SQLite 查询从多个表中删除

    我使用查询来检索具有特定列名称的表列表 select name from sqlite master where type table and sql like unique col id 因此 它返回一个表名称列表 例如 table 1
  • 如何获取应用程序快捷方式的当前目录路径

    我想获取当前目录路径 但不是应用程序位置的路径 而是其快捷方式位置的路径 我尝试了这些 但它们返回了应用程序的位置 Directory GetCurrentDirectory Path GetDirectoryName System Ref
  • 如何在 Django Admin 中覆盖 css?

    我想更改管理 django 中的某些 css 例如base css 直接在django库里改是不是更好 我怎样才能以最好的方式覆盖它 这在很大程度上取决于你想做什么 首先 不要直接在 Django 管理中覆盖它 我认为你有两个合理的选择 如
  • 如何使用 REACT 渲染/更新我的表?

    当我点击时 我无法进行多重交叉过滤Apply 应用我从下拉列表中选择的所有选项 或Cancel按钮 重置所选选项 例如过滤条件taste and availability 请看图片 但我无法呈现过滤后的行 更新的表 export defau
  • IE10 是否支持触摸事件?

    我正在考虑做一个针对使用触摸屏的 Internet Explorer 10 的项目 我目前没有方便的触摸屏 但需要知道 Internet Explorer 10 是否支持或将支持 DOM 触摸事件 Update 触摸事件是开发中在 Inte
  • 如何检查函数调用是否会导致警告?

    在 R 中 如何确定函数调用是否会导致警告 也就是说 在调用该函数后 我想知道该调用实例是否产生了警告 如果您想使用try构造中 您可以设置警告选项 也可以看看 options 更好的是使用tryCatch x lt function i
  • Github推送错误:RPC失败;结果=22,HTTP 代码=413

    Github 现在正在发生愚蠢的问题 我有相当多的更改 大小约为 120MB 当我尝试推送时 会发生以下情况 error RPC failed result 22 HTTP code 413 fatal The remote end hun
  • 基于路径的路由到 cloudfront 和 ec2

    目前我们有两个 ec2 实例 假设 A 和 B 和一个 Cloudfront 如果用户访问 www appdomain com app 用户应该被路由到 cloudfront SPA 页面 但是 如果用户访问 www appdomain c
  • 如何使用 C# 以编程方式将证书安装到本地计算机存储中?

    我有一个通过 MakeCert 生成的证书 我想通过 PeerTrust 将此证书用于 WCF 消息安全 如何使用 C 或 NET 以编程方式将证书安装到 受信任的人 本地计算机证书存储中 我有一个 CER 文件 但也可以创建一个 PFX
  • ASP.NET MVC 3 通用显示模板

    我刚刚开始使用 ASP NET MVC 3 的项目 我正在现有的对象系统之上进行构建 因此我要做的第一件事就是为现有的各种类型定义显示和编辑器模板 在 MVC 中是否可以使用通用参数定义 DisplayTemplate 例如 我们有一个Bi
  • asp.net MVC3 和 jquery AJAX 教程 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心以获得指导 我需要一本非常详细的电子书
  • 在十六进制数组中打印字符缓冲区

    我正在将 512 个字符读入缓冲区 并希望以十六进制显示它们 我尝试了以下方法 但它始终输出相同的值 尽管应该通过网络接收不同的值 char buffer 512 bzero buffer 512 n read connection fd
  • 从 Netbeans 构建时自动签署 JAR

    我想知道 Netbeans 是否有一些选项或设置允许我在构建过程中自动签署 jar In your post jarant target 阅读一下可能会方便来自文件的密码 例如 keyconf 授予文件仅限用户访问权限 例如400 or 6
  • System.Threading.Timer 仅触发一次

    使用下面的代码 计时器仅触发一次 我缺少什么 public static List
  • 如何在Android项目中从头开始设置DAGGER依赖注入?

    如何使用匕首 如何配置 Dagger 在我的 Android 项目中工作 我想在我的 Android 项目中使用 Dagger 但我发现它很混乱 编辑 Dagger2 也于 2015 年 04 月 15 日发布 而且更令人困惑 这个问题是一