我正在寻找关于Android中Dagger 2示波器的快速确认。
在许多在线资源中,您会发现@ActivityScope
和@FragmentScope
被添加到为活动和片段提供绑定的组件中。
我想得到一些确认,这意味着所有活动/所有片段将分别有1个实例。 也就是说,如果两个活动使用相同的组件来接收来自使用范围“活动”注释的同一组件的依赖关系,则两个活动都将接收相同的实例(就像单例注释一样)。
因此,在这种情况下,使用@ActivityScope和@FragmentScope注释只能在活动与片段之间的依赖生存期之间进行隔离。 因此,如果我需要一个依赖项对象,我需要在两个活动中使用一个单独的实例,我应该明确地将它们作为范围(例如@LoginActivityScope)。
你能证实这个假设是正确的吗?
编辑:
阅读有关子组件的文档,它让我有点困惑:
虽然两个不可相互可达的子组件可以与相同的范围相关联,但是没有任何子组件可以与任何祖先组件关联相同的范围,因为没有关于存储范围对象的位置的歧义。 (这两个子组件实际上具有不同的范围实例,即使它们使用相同的范围注释。)
这似乎假设如果您有多个组件使用相同的注释,当相同的scope
注释用于不同的组件时,它会创建一个单独的实例。
我发现scope instance
指的是什么有点不清楚。这实际上是指绑定?
这仅适用于子组件吗?
关于范围与依赖实例(绑定)的一些说明将非常有用。
范围内的组件将在第一次使用时创建范围对象,然后它将保留它。如果第二次创建相同的组件,它也将在第一次使用时创建范围对象。组件只是对象,它们不具有任何全局(静态)状态,因此如果重新创建组件,则会重新创建所有组件。
val component = DaggerScopedComponent.create()
component.getScopedObject() === component.getScopedObject() // always the same object!
// never the same object! two different components, albeit same scope
DaggerScopedComponent.create().getScopedObject() != DaggerScopedComponent.create().getScopedObject()
Dagger生成代码,所以我邀请您创建一个简单的示例并查看代码。例如上面的示例应该非常容易阅读
@Singleton class Foo @Inject constructor()
@Singleton @Component interface ScopedComponent {
fun getScopedObject() : Foo
}
如果您的作用域组件的寿命比其子范围长,那么您必须保留对该组件的引用并重用它。通常的做法是在需要时保持对象的组件的引用,该组件的生命周期(应用程序,活动,片段)。
假设我们在上面的示例中添加了一个子组件
@Singleton class Foo @Inject constructor()
@Singleton @Component interface ScopedComponent {
fun getScopedObject() : Foo
fun subComponent() : SubComponent
}
@Other @Subcomponent interface SubComponent {
fun getScopedObject() : Foo
}
@Scope
@MustBeDocumented
annotation class Other
只要我们使用相同的@Singleton
组件,我们将始终获得相同的@Singleton
范围对象。
// Subcomponents will have the same object as the parent component
component.subComponent().getScopedObject() === component.getScopedObject()
// as well as different Subcomponents
component.subComponent().getScopedObject() === component.subComponent().getScopedObject()
现在回答你的问题......
我想得到一些确认,这意味着所有活动/所有片段将分别有1个实例。也就是说,如果两个活动使用相同的组件来接收来自使用范围“活动”注释的同一组件的依赖关系,则两个活动都将接收相同的实例(就像单例注释一样)。
如上所示,无论哪个子组件,从同一范围组件提供的任何范围对象都是相同的。如果您创建两个@ActivityScope MyActivityComponent
,那么每个组件将创建一个范围@ActivityScoped
的一切。
如果希望在活动组件之间共享对象,则必须使用更高的范围并保留对创建的组件的引用。
因此,在这种情况下,使用@ActivityScope和@FragmentScope注释只能在活动与片段之间的依赖生存期之间进行隔离。
不,因为你可以有一个@ActivityScope FooActivityComponent
和一个ActivityScope BarActivityComponent
,他们永远不会共享一个@ActivityScope class FooBar
对象,它将为每个@ActivityScope
范围组件创建一次。
因此,如果我需要一个依赖项对象,我需要在两个活动中使用一个单独的实例,我应该明确地将它们作为范围(例如@LoginActivityScope)。
@ActivityScope FooActivityComponent
和@ActivityScope LoginActivityComponent
永远不会分享任何@ActivityScope
范围的对象。您可以在此处使用相同的范围。如果你愿意,你也可以创建一个不同的范围,但这里没有任何区别。
这似乎假设如果您有多个组件使用相同的注释,则当相同的范围注释用于不同的组件时,它会创建一个单独的实例。
是的
我发现范围实例所指的内容有点不清楚。这实际上是指绑定?这仅适用于子组件吗?
您不能拥有像Singleton > ActivityScope > ActivityScope
这样的组件层次结构,因为这些重复的范围会使得无法知道@ActivityScope
范围对象是第一个还是第二个的一部分。
您可以拥有相同范围的两个不同组件,即同一父组件的两个子组件(它们不能彼此“到达”),并且任何@ActivityScope
范围对象都将是后一个@ActivityScope
范围组件的一部分。每个组件都有一个范围对象(如上例所示),您可以有两个组件实例或更多。
Singleton > ActivityScope FooComponent
Singleton > ActivityScope BarComponent
我建议你稍微忘掉Android,然后只使用Dagger和生成的代码,就像上面显示的代码一样。这是恕我直言,这是了解事情如何运作的最快方法,一旦“神奇”消失,你会发现它只是一个带有一些变量的POJO。