Dagger 为什么要创建自定义作用域
Dagger why to create custom scope
我正在学习 Dagger,我找到了 this 文章,该文章解释了如何使用 android.dagger
除了自定义创建的作用域外,一切对我来说都很清楚。以前我看过很多教程,其中创建了自定义范围以创建对特定情况的依赖性(例如登录范围)。但是那个教程展示了我的另一种方法。这是我的例子:
我有一个 class 应该只为 MainActivity
(和 MasterActivity
)生成而不是为 LoginActivity
class SecretKey(
val token: String,
val userId: Long
)
这是模块
@Module
class MainActivityModule {
@Provides
fun provideSecretKey(preference: SharedPreferences): SecretKey {
return SecretKey(
"jwtToken",
465465
)
}
}
和 ActivitiesBindingModule
@Module
abstract class ActivitiesBindingModule {
@ContributesAndroidInjector(modules = [MainActivityModule::class])
abstract fun mainActivity(): MainActivity
@ContributesAndroidInjector(modules = [LoginActivityModule::class])
abstract fun loginactivity(): LoginActivity
// MasterActivity will see everything from MainActivityModule and LoginActivityModule
@ContributesAndroidInjector(modules = [MainActivityModule::class, LoginActivityModule::class])
abstract fun masterActivity(): MasterActivity
}
因此,据我所知,仅在 MainActivity
和 MasterActivity
中,由于 ContributesAndroidInjector
模块,我将能够注入 SecretKey
class。所以 SecretKey
范围在 MainActivity
和 MasterActivity
之内。那么,为什么我们仍然能够使用 Scope
注释创建自定义范围?这是替代方案吗?
Scope 只是告诉 Dagger 保存范围注释对象的实例,而不是创建一个新实例。 Dagger 会将实例保存在相应作用域的组件中。 (您还应该知道 @ContributesAndroidInjector
会为您生成一个子组件实例,因此如果您使用范围注释对 @ContributesAndroidInjector
方法进行注释,则生成的子组件将采用该范围。)
在您的示例中,SecretKey 没有作用域;每次你要求 Dagger 注入一个 SecretKey 时,它都会调用你的构造函数并创建一个全新的实例。这可能没问题,因为 SecretKey 似乎不保持状态,并且保持实例 无范围 允许垃圾收集器在您不再需要时收集 SecretKey。
但是,假设您创建了自己的 Cache 对象,并且您希望该 Cache 只要 activity 但不会更长:每个新 Activity 实例应该有自己的缓存。与 SecretKey 不同,您不能在每次请求时都创建自己的缓存;您需要将您的缓存实例保存在某处。您可以选择将此作为 Activity 本身的字段来执行此操作,或者您可以创建一个 Module 实例,在您第一次调用 @Provides
方法时保存实例值,但 Dagger 更喜欢将绑定与组件匹配的作用域注解。这允许您声明和记录绑定将具有与组件相同的生命周期,并且可以轻松地将绑定分类为 "Application-scoped"、"Activity-scoped"、"Fragment-scoped"、"Service-scoped"等等。
我正在学习 Dagger,我找到了 this 文章,该文章解释了如何使用 android.dagger
除了自定义创建的作用域外,一切对我来说都很清楚。以前我看过很多教程,其中创建了自定义范围以创建对特定情况的依赖性(例如登录范围)。但是那个教程展示了我的另一种方法。这是我的例子:
我有一个 class 应该只为 MainActivity
(和 MasterActivity
)生成而不是为 LoginActivity
class SecretKey(
val token: String,
val userId: Long
)
这是模块
@Module
class MainActivityModule {
@Provides
fun provideSecretKey(preference: SharedPreferences): SecretKey {
return SecretKey(
"jwtToken",
465465
)
}
}
和 ActivitiesBindingModule
@Module
abstract class ActivitiesBindingModule {
@ContributesAndroidInjector(modules = [MainActivityModule::class])
abstract fun mainActivity(): MainActivity
@ContributesAndroidInjector(modules = [LoginActivityModule::class])
abstract fun loginactivity(): LoginActivity
// MasterActivity will see everything from MainActivityModule and LoginActivityModule
@ContributesAndroidInjector(modules = [MainActivityModule::class, LoginActivityModule::class])
abstract fun masterActivity(): MasterActivity
}
因此,据我所知,仅在 MainActivity
和 MasterActivity
中,由于 ContributesAndroidInjector
模块,我将能够注入 SecretKey
class。所以 SecretKey
范围在 MainActivity
和 MasterActivity
之内。那么,为什么我们仍然能够使用 Scope
注释创建自定义范围?这是替代方案吗?
Scope 只是告诉 Dagger 保存范围注释对象的实例,而不是创建一个新实例。 Dagger 会将实例保存在相应作用域的组件中。 (您还应该知道 @ContributesAndroidInjector
会为您生成一个子组件实例,因此如果您使用范围注释对 @ContributesAndroidInjector
方法进行注释,则生成的子组件将采用该范围。)
在您的示例中,SecretKey 没有作用域;每次你要求 Dagger 注入一个 SecretKey 时,它都会调用你的构造函数并创建一个全新的实例。这可能没问题,因为 SecretKey 似乎不保持状态,并且保持实例 无范围 允许垃圾收集器在您不再需要时收集 SecretKey。
但是,假设您创建了自己的 Cache 对象,并且您希望该 Cache 只要 activity 但不会更长:每个新 Activity 实例应该有自己的缓存。与 SecretKey 不同,您不能在每次请求时都创建自己的缓存;您需要将您的缓存实例保存在某处。您可以选择将此作为 Activity 本身的字段来执行此操作,或者您可以创建一个 Module 实例,在您第一次调用 @Provides
方法时保存实例值,但 Dagger 更喜欢将绑定与组件匹配的作用域注解。这允许您声明和记录绑定将具有与组件相同的生命周期,并且可以轻松地将绑定分类为 "Application-scoped"、"Activity-scoped"、"Fragment-scoped"、"Service-scoped"等等。