Dagger2范围,每个组件的实例

时间:2019-04-03 22:05:02

标签: android dagger-2

我正在寻找有关Android中Dagger 2示波器的快速确认。

在许多在线资源中,您会发现@ActivityScope@FragmentScope已添加到为活动和片段提供绑定的组件中。

我想确认一下,这意味着所有活动/所有片段分别有1个实例。
也就是说,如果两个活动使用相同的组件来接收来自具有范围“活动”注释的相同组件的依赖关系,则两个活动将接收相同的实例(如单例注释将起作用)。

因此,在这种情况下,具有@ActivityScope和@FragmentScope批注将仅用于区分活动与片段之间的依赖项生存期。
因此,如果我需要在两个活动中需要一个独立实例的依赖项对象,则应明确地对其进行范围划分(例如@LoginActivityScope)。

您能确认这个假设是正确的吗?

修改:

阅读有关子组件的文档,这使我有些困惑:

  

任何子组件不得与任何祖先具有相同的范围   组件,尽管两个子组件无法相互访问   可以与同一范围相关联,因为没有歧义   关于将范围对象存储在何处。 (两个子组件   有效地拥有不同的作用域实例,即使它们使用相同的实例   范围注释。)

这似乎假设如果您有多个使用相同批注的组件,则当将相同的scope批注用于不同组件时,它的确会创建一个单独的实例。

我对scope instance所指的含义还不清楚。这实际上是指绑定吗?
这仅适用于子组件吗?

对范围和依赖实例(绑定)进行一些澄清将非常有帮助。

1 个答案:

答案 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,其中包含一些变量。