我正在寻找有关Android中Dagger 2示波器的快速确认。
在许多在线资源中,您会发现@ActivityScope
和@FragmentScope
已添加到为活动和片段提供绑定的组件中。
我想确认一下,这意味着所有活动/所有片段分别有1个实例。
也就是说,如果两个活动使用相同的组件来接收来自具有范围“活动”注释的相同组件的依赖关系,则两个活动将接收相同的实例(如单例注释将起作用)。
因此,在这种情况下,具有@ActivityScope和@FragmentScope批注将仅用于区分活动与片段之间的依赖项生存期。
因此,如果我需要在两个活动中需要一个独立实例的依赖项对象,则应明确地对其进行范围划分(例如@LoginActivityScope)。
您能确认这个假设是正确的吗?
修改:
阅读有关子组件的文档,这使我有些困惑:
任何子组件不得与任何祖先具有相同的范围 组件,尽管两个子组件无法相互访问 可以与同一范围相关联,因为没有歧义 关于将范围对象存储在何处。 (两个子组件 有效地拥有不同的作用域实例,即使它们使用相同的实例 范围注释。)
这似乎假设如果您有多个使用相同批注的组件,则当将相同的scope
批注用于不同组件时,它的确会创建一个单独的实例。
我对scope instance
所指的含义还不清楚。这实际上是指绑定吗?
这仅适用于子组件吗?
对范围和依赖实例(绑定)进行一些澄清将非常有帮助。
答案 0 :(得分:1)
作用域组件将在第一次使用时创建作用域对象,然后将其保留。如果第二次创建相同的组件,它将在第一次使用时创建作用域对象。组件只是对象,它们不具有任何全局(静态)状态,因此,如果重新创建该组件,则将重新创建所有内容。
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 FooActivityComponent
。
如果要在“活动”的组件之间共享对象,则必须使用 higher 范围,并保留对创建的组件的引用。
因此,在这种情况下,具有@ActivityScope和@FragmentScope批注仅在区分活动与片段之间的依赖项生存期时有用。
否,因为您可以拥有一个ActivityScope BarActivityComponent
和一个@ActivityScope class FooBar
,并且它们将永远共享一个@ActivityScope
对象,该对象将为每个{ {1}}范围内的组件。
因此,如果我需要在两个活动中需要一个独立实例的依赖项对象,则应明确地对其进行范围设置(例如@LoginActivityScope)。
@ActivityScope FooActivityComponent
和@ActivityScope LoginActivityComponent
将从不共享任何@ActivityScope
范围内的对象。您可以在此处使用相同的范围。您也可以根据需要创建其他范围,但这在这里没有区别。
这似乎是假设,如果您有多个使用相同批注的组件,则当对不同组件使用相同的范围批注时,确实会创建一个单独的实例。
是
我发现范围实例所指的内容还不清楚。这实际上是指绑定?这仅适用于子组件吗?
您无法拥有Singleton > ActivityScope > ActivityScope
之类的组件层次结构,因为这些重复的作用域将使您无法知道@ActivityScope
范围内的对象是第一个对象还是第二个对象的一部分。
您可以在同一范围内拥有两个不同的组件,同一父级的两个子组件(它们彼此无法“到达”),并且任何@ActivityScope
范围内的对象都将是后者{{1 }}作用域组件。每个组件将有一个作用域对象(如上面的示例所示),并且可能有两个或更多组件实例。
@ActivityScope
Singleton > ActivityScope FooComponent
我建议您稍微忘记一下Android,然后像上面显示的代码那样使用Dagger和生成的代码。这是恕我直言,这是找出事物运作方式的最快方法,一旦“魔术”消失了,您会发现它只是一个POJO,其中包含一些变量。