来自User's Guide:
有时您希望限制@Inject构造的次数 class被实例化或调用@Provides方法,但你没有 需要保证在期间使用完全相同的实例 任何特定组件或子组件的生命周期。
为什么我会使用它代替@Singleton
?
答案 0 :(得分:63)
如果您依赖单身行为和保证,请使用@Singleton。如果出于性能原因,对象只是@Singleton,请使用@Reusable。
@Reusable绑定与未绑定的绑定有更多共同点@Singleton绑定:你告诉Dagger你可以创建一个全新的对象,但是如果有一个方便的对象已创建然后Dagger 可能使用那个。相比之下,@ Singleton对象保证您将始终接收相同的实例,这可能会更加昂贵。
一般来说,Dagger和DI更喜欢未绑定的对象:创建新对象是保持状态紧密包含的好方法,并且允许在依赖对象可以时对对象进行垃圾收集。 Dagger显示了一些内置的首选项:在Dagger中,未编组的对象可以混合到任何组件或模块中,无论组件是否是范围注释的。这种类型的无范围绑定对于无状态对象(如可注入(可模拟)实用程序类)以及strategy,command和其他多态behavioral design patterns的实现也很有用:对象应该受到全球约束并注入测试/覆盖,但实例不保留任何状态,短期或一次性。
然而,在Android和其他性能和内存受限的环境it goes against performance recommendations to create a lot of temporary objects中,因为实例创建和垃圾收集都是比桌面虚拟机更昂贵的进程。这导致了标记对象@Singleton的实用解决方案,并不是因为始终获得相同的实例非常重要,而只是为了保存实例。这有效,但在语义上很弱,并且还有内存和速度含义:只要您的应用程序存在,您的短期工具或策略模式对象现在必须存在,并且必须通过双重访问 - 检查锁定,否则你可能会违反"仅一个实例" @Singleton保证(这里不必要)。这可能是内存使用量增加和同步开销增加的原因。
妥协在@Reusable绑定中,它具有像@Singleton这样的实例保存属性,但excepted from the scope-matching @Component rule就像未绑定的绑定一样 - 这使您可以更灵活地安装它们。 (参见tests。)它们的寿命只有直接使用它们的最外层组件,并且会机会性地使用来自祖先的实例来进一步保存,但without double-checked locking可以节省创建成本。最后,最重要的是,它们向您和未来的开发人员发出了关于该课程的使用方式的信号。
简而言之,@ Singleton可以工作,但如果整个点是性能而不是对象生命周期,@ Reusable有一些明显的性能优势。
来自saiedmomen的后续问题:"只需要100%清除okhttpclient,retrofit和gson之类的东西应该声明为@Reusable。右??"
是的,总的来说,我认为将无状态实用程序和库声明为@Reusable
是件好事。但是,如果他们秘密保留一些类似状态的处理连接限制或在所有消费者之间进行批处理 - 您可能希望将它们设为@Singleton
,并且如果它们很少使用来自长期存在的组件使它们无范围可能仍然有意义,因此它们可以被垃圾收集。在这里制作适用于所有案例和库的一般性陈述真的很难:您必须根据库功能,内存权重,实例化成本和所涉及对象的预期寿命来决定。
OkHttpClient特别是manage its own connection and thread pools per instance,正如Wyko在评论中指出的那样;这将使其成为@Singleton
优于@Reusable
的合适人选。谢谢Wyko!