我试图了解Dagger的@Reusable范围的使用。从文档中,我可以理解的是,如果提供程序的范围是@Singleton或任何其他自定义范围,则将首先创建对象,然后在组件的整个生命周期内对其进行缓存。因此,对于并非总是需要相同实例或不经常使用的对象,这种方法最终会浪费内存。

但是,如果我们选择一个非作用域的提供程序,则每次创建一个新实例时,由于对象实例化是昂贵的,尤其是在Android这样的环境中(分配可能是昂贵的),这可能导致性能问题。
@Reusable范围位于No-scope和Scoped实例之间。
从文档中



究竟如何运作?假设我的AppComponent中有一个可重用的提供程序,难道它不总是给我相同的实例吗?

如果我在任何Subcomponent中注入(inject)相同的依赖项,是否会得到相同的实例?何时才将缓存的对象释放给GC?

我尝试了一个示例,在我的@Reusable模块中创建了一个AppComponent对象,并将其从我的子组件中注入(inject)。
我看到的是它的行为与@Singleton完全相同。

@Reusable可以实现哪些性能改进?

我们应该首选@Reusable的可能用例有哪些?

将所有无状态对象(无论是否获得相同的实例)(如Util类,Gson,Glide等)的范围限定为@Reusable是一个好主意吗?

最佳答案

我想指出的是,从v2.13开始,@Reusable仍处于beta中,因此可能会再次更改或删除它。
tl; dr 它的行为就像变量作用域,不能保证在任何给定时间只有一个实例。

Javadoc在该主题上非常(不清楚):

它没有提供任何有关其幕后工作方式的信息,并且您不应该依赖任何可能的实现,因为它们可能会发生变化,尤其是当它仍在@Beta中时。
假设@Reusable可以用于可以多次存在的对象,但是多个对象的实例化可能会花费更多,因此有意义的是可以重用该对象。
虽然实现可能会更改,但预期的用途不会改变。因此,如果您决定使用@Reusable,则应来确保您是否拥有对象的一个,两个或多个实例,无论它们在何处或是否被缓存都无关紧要。

如前所述,您应该使用它,就像名称所暗示的那样,可以重用一个对象。 Gson是一个非常糟糕的示例,因为它使用了很多反射,并且其实例化非常昂贵,因此它可能应该是@Singleton。 Glide也不是一个很好的例子,因为无论如何它都会在内部使用Singleton模式。@Reusable优于@Singleton的一个好处是,您无需声明作用域或组件之间的层次结构。将对象设置为@Singleton意味着您的AppComponent将在整个生命周期内保留该对象,而使用@Reusable则只能在依赖项树的整个子级中的子组件中创建该对象,并再次将其销毁。
我不会将其用于具有很少依赖性的对象,因为它们可以很容易地创建,但不会将其用于不持有任何状态并且需要更多设置的对象。
但是它是如何工作的呢?
可重用是一种经过特殊处理的@Scope。您可以看到commit where it was added
作为范围,使用@Reusable注释的对象将保存在组件内。您可以看一下第一个单元测试。它验证子组件将重用其父级的提供者(如果有)。这是您提到的行为,为什么它与@Singleton没什么关系。
与正常作用域的区别在于所使用的Provider。代替使用 ScopedProvider @Reusable使用 SimpleLazilyInitializedProvider 。它在创建对象时省略了synchronized关键字,这可能会略微提高性能,但解​​释了为什么没有特定生存期的情况,因此只能有一个实例。
如果他们将来更改@Reusable的内部工作原理,我不会感到惊讶,但是就目前而言,知道它的作用范围很广,可能有助于决定何时使用它。

关于android - Dagger 2中@Reusable范围的用途是什么,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47742002/

10-11 22:19