Java 在Android中使用(out)DI容器进行适当的依赖注入(Dagger 1)

Java 在Android中使用(out)DI容器进行适当的依赖注入(Dagger 1),java,android,dependency-injection,inversion-of-control,dagger,Java,Android,Dependency Injection,Inversion Of Control,Dagger,我目前正在开发(实际上正在构建)一个Android应用程序,它具有蓝牙连接和HTTP通信以及RESTful服务。我碰巧遇到了一个名为Dagger的“依赖注入”框架,它对我来说是革命性的。然而,我开始更多地思考依赖注入的“真正精神”,并遇到更多的博客文章/观点来解释这个概念,实际上建议使用“构造函数注入”,并将其他(字段和setter注入)标记为“反模式” 我确实了解到他们对通过DI框架进行字段和setter注入的担忧,因为前者没有显式地揭示对象的依赖关系,而后者也没有严格地“要求”依赖关系然而,

我目前正在开发(实际上正在构建)一个Android应用程序,它具有蓝牙连接和HTTP通信以及RESTful服务。我碰巧遇到了一个名为Dagger的“依赖注入”框架,它对我来说是革命性的。然而,我开始更多地思考依赖注入的“真正精神”,并遇到更多的博客文章/观点来解释这个概念,实际上建议使用“构造函数注入”,并将其他(字段和setter注入)标记为“反模式”

我确实了解到他们对通过DI框架进行字段和setter注入的担忧,因为前者没有显式地揭示对象的依赖关系,而后者也没有严格地“要求”依赖关系然而,一些人提出了强烈的观点,认为依赖注入唯一有效、有用、真正面向对象的方法是构造函数注入

我特别关心的是Android。开发一个Android应用程序意味着要处理很多活动、服务、片段、广播接收器等等,其中很多都不让我们处理构造函数。为了使用DI容器(Dagger)提供依赖项,我只需要对依赖项使用字段注入为什么不使用POJO工厂?使用DI框架进行现场注入的唯一优势似乎是能够提供单独的模块(一个用于生产,另一个用于注入模拟对象进行测试),但我不知道是否值得引入性能开销(如果有)

就目前而言,在我严格限制的观点中,使用Dagger的唯一优点是减少了要编写的代码量,避免了连接对象以正确传递依赖关系所带来的麻烦

因此,我得出了一个结论,我可能完全误解了依赖注入的概念,或者/或者我错过了使用Dagger的正确方法,或者/或者我在面向对象设计中过于固执己见(或者不是很有能力)


请教育我如何正确使用DI容器以及缺乏洞察力/理解

TL;DR:不必将类连接在一起是一个巨大的优势,在重构过程中不必重新连接是一个更大的优势

我发现你的“唯一优势”仍然是一个巨大的优势。IMHO,DI最有价值的部分出现在您添加或重构现有代码时。我经常遇到这样一种情况,依赖关系图的“叶子”上的某个东西需要从图的根中得到一些额外的东西(即UserStorageHelper需要一个上下文)。在没有DI的情况下,有必要在某个根依赖项和目标依赖项之间通过构造函数和/或onCreate/onAttach的每一层传递该对象。DI将允许您以最小的重构成本添加该依赖项。在我看来,它使代码更容易理解,因为在每个级别上,您都可以检查并说“这个对象需要一些依赖项”。这些对象所具有的任何子依赖项都不是立即有用的信息,但您也可以轻松地进行检查。(Dagger还可以生成依赖关系图,如果您想要一个概览的话,我认为这非常简洁。)

与此相反的是,更改“叶”对象的依赖关系可能会在图形上产生涟漪效应,而这并不一定是显而易见的。然而,当您需要修改依赖关系图中的每个构造函数时,我通常会发现修复DI问题比潜在的大规模重构要好

对于使用POJO工厂的建议,在我看来,您仍然存在相同的依赖性问题。工厂的每一层都需要另一个工厂来获取其依赖项。自己编写似乎也同样乏味,所以您可以通过代码生成它,但现在您基本上只有dagger的提供者

除了在测试中提供不同的实现之外,我还广泛地使用它来处理构建风格/维度/构建类型(注入不同类型的记录器模块?没有op模块还是真正的ad模块?)


最终,有用性完全取决于您的项目。Dagger/DI在很多情况下都非常有用,但不是所有情况下都有用。有点像一个多工具,你可以用很多不同的方式使用它。有时这是一种过分的手段(你只需要一个螺丝刀,而不是一个酒瓶开瓶器),有时它根本解决不了你的问题(不管你怎么努力,它都不会成为一个好锤子)。唯一需要注意的是,延迟添加DI要比从一开始就使用DI困难得多,因此我倾向于在项目开始时将其作为一个过度的选项添加,而不是进入一个项目并希望我已经拥有它。

我也有同样的问题。我希望有人能帮忙。我所看到的每一篇教程都提倡使用构造函数来注入依赖项,但正如你所说的,这在Android中是行不通的。老实说,这是一个很好的答案。在最近的一个项目开始时,我开始使用Dagger,这似乎有点过头了。随着项目的进展,我发现自己正处于上述情况(重构只是为了在叶类中添加依赖项)。后来我很高兴我在代码中留下了Dagger:)因为具有生命周期的特定于Android的类倾向于无论如何都不支持显式构造函数调用,所以你的想法似乎非常合理,我现在完全可以务实地同意。感谢您在这个问题上如此明确!