【问题标题】:Starting out with Dagger 2 - class not injecting从 Dagger 2 开始 - 类不注入
【发布时间】:2018-01-07 20:21:52
【问题描述】:

我正在尝试将singleton 存储库注入Foo 类以使用它。
repo 没有注入并且仍然为空,为什么我缺少一些注释或者这不是正确的方法

Repository.java

@Singlton
public class Repository {...} 

Foo.java

public class Foo {
  @Inject Repository repo;
}

【问题讨论】:

    标签: java dependency-injection singleton dagger


    【解决方案1】:

    Dagger 通过 Components 工作:具体来说,您向 Dagger 传递您想要或想要做的事情的列表(组件接口)以及您希望如何提供重要的依赖项(模块),然后 Dagger 会生成你想要的接口的实现。

    您已经向我们展示了 Foo 及其依赖存储库,但如果您没有向我们展示组件,我猜您可能没有。此时您可以选择如何进行:您可以从 Dagger 组件中获取 Foo,也可以像往常一样创建 Foo,然后调用 inject(foo) 以注入特定的 Foo 实例及其所有 @Inject字段(包括您的存储库)。前者通常更适合制作简单的界面,但后者适用于您无法控制生命周期的对象(如 Android 的 Application、Activity、Fragment、Service 和其他类似对象)。

    获取 Foo

    如果你选择让 Dagger 创建你的 Foo,你需要为 Foo 和 Repository 创建一个@Inject-annotated 构造函数(甚至是一个空的),然后编写像这样的组件

    @Component public interface YourComponent {
      Foo createFoo();  // Name this whatever you like; it's a factory because
                        // of its return type and lack of parameters.
    }
    

    太棒了!现在只要你有一个 YourComponent 的实现,你就可以创建一个 Foo 并注入它。你还没有写过实现,但如果你写了,它可能看起来像这样:

    public YourComponentImpl implements YourComponent {
      @Override public Foo createFoo() {
        Foo foo = new Foo();
        foo.repo = new Repository();
        return foo;
      }
    }
    

    但是,你不必写一个:Dagger 会在你compile the YourComponent interface with the Dagger compiler 时立即为你写一个与上面那个等价的,这意味着用javac 编译它将 Dagger 编译器指定为源代码处理器。 Dagger 作为一个注解处理器,它读取@Component 接口并生成一个名为 DaggerYourComponent 的类。之后,您可以通过调用静态方法DaggerYourComponent.create() 来获取一个实例,然后在该实例上调用yourComponent.createFoo(),否则您将调用new Foo()

    注入现有的 Foo

    要注入,您遵循与上述类似的模式,除了您的方法应该采用一个参数(您现有的 Foo 实例),因此您不需要将 @Inject-annotated 构造函数添加到 Foo 因为 Dagger 没有永远不要建造一个。不过,你为 Repository 做,因为 Dagger 会创建它。

    @Component public interface YourComponent {
      void inject(Foo foo);  // Name this whatever you like; it's a members injector
                             // because it takes exactly one argument.
    }
    

    这将允许您像上面一样调用DaggerYourComponent.create() 来创建组件,然后调用yourComponent.inject(foo) 将存储库注入到您注释的repo 字段中。

    一旦您对 Dagger 更加熟悉,您就可以开始构建您所知道的内容并添加模块、使用 Provider<> 注入或添加范围以便重用实例而不是创建每次都有新的。更多信息请查看User's Guide

    【讨论】:

    • 非常感谢,这是一个简单直接的解释,花了我 2 天的时间搜索和试验,但我有一个关于你不拥有的课程的问题,比如活动、服务等......你需要将类实例传递给生成的匕首组件inject() 方法的第二种方法,以填写成员字段依赖项。如果你想测试一个活动,你在onCreate()中调用我的生产组件的inject(this),如果我需要切换到另一个MockComponent,有没有一种简单的方法可以不用每次都更改活动代码..
    • 我的意思是我可以从 Activity 中调用 inject() 以使其独立于选择特定组件,但是在生产中你不能这样做,你必须从 Activity 内部注入,并且使用dagger-android 让我很头疼,我喜欢在了解基础知识后制定自己的解决方案。
    • 对于一个简单的dagger.android 等价物,你的Activity 应该调用getApplication(),然后你通过getComponent() 之类的方法公开你的组件,然后你调用inject(this) 确保你的组件有FooActivity、BarActivity 等的特定方法。 (普通的 Activity 不起作用,因为 Dagger 为您的每个类编写了不同的实现。)如果您无法编写适合您的测试需求的 Application 子类,请考虑提取 getApplication().getComponent() 调用并强制转换为 方法,然后在测试中对其进行子类化
    【解决方案2】:

    你有没有初始化你的注入器并声明你的单例?例如,通过创建一个用@Module 注释的类来向Dagger 发出信号,以便在可用方法中搜索可能的实例提供程序。尝试关注this 示例。

    【讨论】:

    • 感谢您的回复,是的,我试过了也没有用,我还测试了一个非常简单的 Injection 只是一个在我的MainActivity 中用@Inject 注释的类Bar 字段,这也是保持未注入并且仍然为空我是否缺少一些 Dagger 初始化或什么问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-13
    • 1970-01-01
    • 2022-09-30
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多