为什么 Dagger 组件必须声明它们的作用域?
Why do Dagger components have to declare their scope?
为什么我必须用 Dagger 组件将要使用的范围来注释它?为什么注释 class 本身还不够?
我们需要本地化,因为我们不希望我们所有的依赖项都与应用程序一样长,并且在某些情况下,我们希望我们的依赖项不因为是同一个对象而共享相同的状态。
Activity 有自己的 Presenters 或 ViewModels,1 个或多个 Presenters 或 ViewModels 可能需要一个 Interactor,Interactors 取决于数据层。 Dagger 2 提供@Scope 作为处理作用域的机制。作用域允许您保留对象实例,并在作用域组件的持续时间内将其作为本地单例提供。
只要范围存在,范围就会关心保持 class 的单个实例。实际上,这意味着 @ApplicationScope 范围内的实例与 Application 对象一样长。只要 Activity 存在,@ActivityScope 就会保留引用(例如,我们可以在这个 Activity 中托管的所有片段之间共享任何 class 的单个实例)。
简而言之 - 范围为我们提供了与范围本身一样长的“本地单例”。
因为范围本身没有任何意义。是组件及其关系为范围引入了意义。
如果依赖项可用,则可以从任何组件提供未限定范围的对象。由于它们是无范围的,因此每次调用它们的提供者时都会创建一个新对象。作用域对象将共享同一作用域组件的生命周期,并且每个组件只会创建 一次。如果重新创建组件,则会重新创建其范围内的所有对象。这就是事情变得棘手的地方。
假设您有以下设置:一个组件和一个子组件,通常是这种情况。
@Component interface MyComponent {}
@Subcomponent interface MySubComponent {}
现在假设我们有两个 class,@FooScope
中的 Foo
和 @BarScope
中的 Bar
。两者都支持构造函数注入,并且在各自的 class 上都有范围注释。假设我们为我们的子组件添加了两者的提供方法:
@Subcomponent
interface MySubComponent {
Foo getFoo();
Bar getBar();
}
现在有个大问题:在哪里创建 Foo
或 Bar
,它们共享哪个组件的 "lifecycle"?
我们确实知道 Foo
和 Bar
属于不同的范围,但仅此而已。如果一个依赖于另一个,我们 可能 能够推断出一个位于(父)组件中而另一个位于子组件中,因为一个只能依赖于相同或一个的对象更高的范围,但这只适用于这个简单的设置,如果我们决定向这个设置添加第三个组件,将会再次给我们带来不确定性。
如果我们有 3 个范围,但只有两个组件会怎样?这两个组件中的哪一个应该承载两个范围(如果这有意义的话)?或者如果是报错,哪个scope是"the wrong one"?根本无法确定。
如果您还向组件添加作用域,这些问题就会消失。现在很清楚哪个组件处理哪些(范围内的)对象,并且在引入未知范围时很容易报告错误。
为什么我必须用 Dagger 组件将要使用的范围来注释它?为什么注释 class 本身还不够?
我们需要本地化,因为我们不希望我们所有的依赖项都与应用程序一样长,并且在某些情况下,我们希望我们的依赖项不因为是同一个对象而共享相同的状态。 Activity 有自己的 Presenters 或 ViewModels,1 个或多个 Presenters 或 ViewModels 可能需要一个 Interactor,Interactors 取决于数据层。 Dagger 2 提供@Scope 作为处理作用域的机制。作用域允许您保留对象实例,并在作用域组件的持续时间内将其作为本地单例提供。 只要范围存在,范围就会关心保持 class 的单个实例。实际上,这意味着 @ApplicationScope 范围内的实例与 Application 对象一样长。只要 Activity 存在,@ActivityScope 就会保留引用(例如,我们可以在这个 Activity 中托管的所有片段之间共享任何 class 的单个实例)。 简而言之 - 范围为我们提供了与范围本身一样长的“本地单例”。
因为范围本身没有任何意义。是组件及其关系为范围引入了意义。
如果依赖项可用,则可以从任何组件提供未限定范围的对象。由于它们是无范围的,因此每次调用它们的提供者时都会创建一个新对象。作用域对象将共享同一作用域组件的生命周期,并且每个组件只会创建 一次。如果重新创建组件,则会重新创建其范围内的所有对象。这就是事情变得棘手的地方。
假设您有以下设置:一个组件和一个子组件,通常是这种情况。
@Component interface MyComponent {}
@Subcomponent interface MySubComponent {}
现在假设我们有两个 class,@FooScope
中的 Foo
和 @BarScope
中的 Bar
。两者都支持构造函数注入,并且在各自的 class 上都有范围注释。假设我们为我们的子组件添加了两者的提供方法:
@Subcomponent
interface MySubComponent {
Foo getFoo();
Bar getBar();
}
现在有个大问题:在哪里创建 Foo
或 Bar
,它们共享哪个组件的 "lifecycle"?
我们确实知道 Foo
和 Bar
属于不同的范围,但仅此而已。如果一个依赖于另一个,我们 可能 能够推断出一个位于(父)组件中而另一个位于子组件中,因为一个只能依赖于相同或一个的对象更高的范围,但这只适用于这个简单的设置,如果我们决定向这个设置添加第三个组件,将会再次给我们带来不确定性。
如果我们有 3 个范围,但只有两个组件会怎样?这两个组件中的哪一个应该承载两个范围(如果这有意义的话)?或者如果是报错,哪个scope是"the wrong one"?根本无法确定。
如果您还向组件添加作用域,这些问题就会消失。现在很清楚哪个组件处理哪些(范围内的)对象,并且在引入未知范围时很容易报告错误。