了解Dagger 2 app Architecture

时间:2015-10-01 15:31:00

标签: java dagger-2

我正试图绕过Dagger 2和Dependency Injection。我认为这样做的好方法是看看官方Coffee example。我还阅读了github页面上的官方文档,但我发现它对新手来说相当混乱。

正如您在下图所示,我删除了所有课程,并将其着色以了解正在发生的事情。但我还是有些疑惑

Coffee Classes

我的问题:

1)我听说我们使用DI,因为在构造函数上传递依赖项会使我们的代码变得冗长。好吧,这个例子中的代码和类的数量远远超过了在构造函数中提供这两个参数所需的量。此外,代码将更加人性化。这样做有什么好处?

2) PumpModule 声明一个提供程序,它接受它应该提供的东西作为参数...这是一个有点反直觉。那里到底发生了什么?

3)我真的迷路了(CoffeApp.java)

DaggerCoffeApp_Coffe.builder().build()

那是做什么的?哪里是DaggerCoffeApp_Coffe? Android工作室表示无法在任何地方找到它。

1 个答案:

答案 0 :(得分:3)

回答1

  

“此示例中的代码和类的数量极大地超出了   如何在a中提供这两个参数   构造函数“

在示例代码或非常小的应用程序中 - 是的。在正常大小或大型应用程序中,如果不是成千上万次,你将有猎人提供“构造函数中的这两个参数”。

DI的最大优势之一是它允许(并且在某种程度上可能会强制)您创建模块化应用程序,其中模块可以单独开发和测试。这可能听起来不是什么大问题但是,当应用程序变得越来越大时,在不破坏事物的情况下添加新的更改变得非常困难。在开发模块时,您可以通过定义提供所需功能的接口并为这些接口定义@Inject来将自己与应用程序的其余部分隔离开来。这样,如果你以后(几个月,下一个版本?)决定你需要更改/扩展/重写某些模块,只要你不改变它的界面,其他模块就不会受到影响。您可以编写替换模块,然后在@Provides方法中“切换”它。

DI的另一大优势是它可以让您轻松地将模拟对象提供给单元测试。例如:假设您有Activity使用GPS位置提供程序来检测位置。如果你想在没有DI的情况下测试它,你必须在调试模式下在模拟器中运行你的应用程序,手动提供一些“假”位置,并在某个断点检查活动是否处于预期状态。使用DI,您可以轻松地将模拟位置提供程序提供到Activity模拟GPS位置更新的模拟GPS位置更新中。当然,您可以再次在模拟器(或真实设备)中手动运行您的应用程序,但您也可以在单元测试中自动运行它,甚至可以在像Jenkins这样的持续集成服务器进程中运行它。这样,每次更改代码时,您都可以运行测试并立即查看更改是否有所改变。另一个值是自动测试可以节省您的时间。在该示例中,您可能需要至少2分钟进行手动测试。自动测试需要几秒钟,更重要的是它将在运行时无需您的注意/输入即可运行。

有关更多信息,我推荐杰克沃顿的这个精彩视频: https://www.parleys.com/tutorial/5471cdd1e4b065ebcfa1d557/

这里是视频的幻灯片: https://speakerdeck.com/jakewharton/dependency-injection-with-dagger-2-devoxx-2014

回答2

  

“PumpModule声明一个提供者,它接受它应该的东西   提供参数“

该提供者提供接口,而不是具体类。这就是重点。将应用程序迁移到DI时,必须为要注入的每个类创建一个接口。如答案1中所述,通过这种方式,您将能够轻松地使用模拟对象替换具体实现以进行测试,或者为应用程序的更高版本提供更好的更好实现。 例如:在某些时候,您决定需要旋转叶片泵而不是Thermosiphon。您编写了RotaryVanePump课程,然后只需将方法更改为@Provides Pump providePump(RotaryVanePump pump) {

这是如何工作的((简化)简化说明):

  1. DaggerCoffeApp_Coffe.builder().build()构建的DI图(请先参阅答案3)
  2. Dagger在某些时候会在您的代码中找到@Inject Pump mMyPump;
  3. Dagger发现您需要注入泵并在DI图中寻找如何提供它。
  4. 找到@Provides Pump providePump()方法。 Dagger认为它需要RotaryVanePump对象。
  5. Dagger在DI图中寻找如何提供RotaryVanePump
  6. 任何模块中都没有provide方法,但RotaryVanePump不需要一个,因为它有无参数构造函数,因此Dagger可以实例化一个对象。
  7. 新对象的实例化类型为RotaryVanePump
  8. Dagger在providePump()中将此对象作为实际参数提供。
  9. providePump()返回该对象作为返回值。
  10. RotaryVanePump被注入@Inject Pump mMyPump字段。
  11. 所有这一切都是自动完成的,你不必关心它。

    回答3

    DaggerCoffeApp_Coffe由Dagger生成。你必须使用这个才能让Android工作室“看到”生成的类。 https://bitbucket.org/hvisser/android-apt

      

    “那是做什么的?

    这是在做整个魔术:-)。它构建依赖关系图并检查在编译时是否满足所有依赖关系。 “在编译时”将Dagger与在编译时无法验证图形的所有其他DI框架区分开来,如果您错过定义某些依赖项,您将得到一个难看的运行时错误。

    为了使您的所有@Inject工作,您必须首先使用此类调用构建图表。