Dependency injection Dagger@可重用范围vs@Singleton

Dependency injection Dagger@可重用范围vs@Singleton,dependency-injection,dagger-2,Dependency Injection,Dagger 2,从: 有时,您希望限制@Inject的构造次数 类被实例化或@Providers方法被调用,但您没有 需要保证在测试过程中使用完全相同的实例 任何特定组件或子组件的寿命 如果依赖于单例行为和保证,为什么我要使用它而不是单例呢。如果出于性能原因,对象只能是@Singleton,请使用@reusabled @与@Singleton绑定相比,可重用绑定与非范围绑定有更多的共同点:您告诉Dagger您可以创建一个全新的对象,但如果已经创建了一个方便的对象,Dagger可能会使用该对象。相比之下,@Si

从:

有时,您希望限制@Inject的构造次数 类被实例化或@Providers方法被调用,但您没有 需要保证在测试过程中使用完全相同的实例 任何特定组件或子组件的寿命


如果依赖于单例行为和保证,为什么我要使用它而不是单例呢。如果出于性能原因,对象只能是@Singleton,请使用@reusabled


@与@Singleton绑定相比,可重用绑定与非范围绑定有更多的共同点:您告诉Dagger您可以创建一个全新的对象,但如果已经创建了一个方便的对象,Dagger可能会使用该对象。相比之下,@Singleton对象保证您将始终收到相同的实例,这可能需要花费更高的实施成本

一般来说,Dagger和DI更喜欢非作用域对象:创建一个新对象是保持状态被严格控制的好方法,并且允许在依赖对象可以被垃圾回收时尽快对对象进行垃圾回收。Dagger显示了一些内置的首选项:在Dagger中,未作用域的对象可以混合到任何组件或模块中,而不管该组件是否带有范围注释。这种类型的非范围绑定也适用于无状态对象,如的可注入(可模拟)实用程序类和实现,以及其他多态对象:对象应全局绑定并注入以进行测试/重写,但实例不保留任何状态和短期或一次性

然而,在Android和其他性能和内存受限的环境中,因为实例创建和垃圾收集都是比桌面虚拟机更昂贵的过程。这导致了将一个对象标记为@Singleton的实用解决方案,这不是因为始终获得相同的实例很重要,而是为了保存实例。这是可行的,但在语义上很弱,而且还涉及内存和速度:只要应用程序存在,您的短期util或strategy pattern对象现在就必须存在,并且必须通过双重检查锁定进行访问,否则您就有可能违反“仅一个实例”@Singleton保证(这在这里是不必要的)。这可能会增加内存使用和同步开销

折衷的办法是@ReusableBindings,它具有@Singleton之类的实例保护属性,但与unscoped绑定一样,它在安装位置上给了您更多的灵活性。(请参阅。)它们的使用寿命仅与直接使用它们的最外层组件的使用寿命相同,并且会机会主义地使用来自祖先的实例来进一步保存,但可以节省创建成本。最后,也是最重要的一点,它们是向您和未来的开发人员发出的关于类的使用方式的信号

简言之,@Singleton可以工作,但是如果整个重点是性能而不是对象生命周期,@reusible有一些明显的性能优势



后续问题来自:“为了100%清楚,像okhttpclient、改装和gson之类的东西应该声明为@Reusables。对吧??”

是的,一般来说,我认为最好将无状态实用程序和库声明为可重用的。但是,如果它们秘密地保留一些状态,比如处理连接限制或在所有使用者之间进行批处理,那么您可能希望使它们成为
@Singleton
,并且如果它们很少从长寿命组件中使用,那么将它们设为无作用域可能仍然有意义,这样它们就可以被垃圾收集。在这里很难做出一个适用于所有案例和库的通用声明:您必须根据库功能、内存重量、实例化成本和所涉及对象的预期寿命来决定


正如评论中指出的,OkHttpClient尤其如此;这将使它成为
@Singleton
而不是
@reusabled
的一个很好的候选者。谢谢Wyko

为了100%清楚,像okhttpclient、改装和gson这样的东西应该声明为@Reusables。对吧???@saiedmomen我不会声明
OkHttpClient
是可重用的。根据文档,最好在整个应用程序中重用单个实例:Jake Wharton说,“RestaAdapter和生成的服务实例(本例中为MyTaskService)是非常昂贵的对象,应该作为单例使用(…)您应该只调用restAdapter.create一次,并在每次需要与“”交互时重新使用相同的MyTaskService实例。来源:如果我使用@Reusables,基本上,我无法理解我的类Instances的生命周期。我有这些问题,1)在任何时间点上都只有一个实例最大值,2)如果没有,它什么时候创建新对象(通过,已经有一个可用),3)它什么时候重用现有对象,4)什么时候垃圾收集对象。非常感谢。