匕首为何要创建自定义范围

时间:2018-08-29 17:50:49

标签: android dependency-injection dagger-2 dagger

我正在学习匕首,并且我找到了this文章,该文章解释了如何使用android.dagger对我来说很清楚,除了使用自定义创建的范围。以前我看过很多教程,其中创建了自定义范围以创建对特定情况的依赖关系(例如,Logged In范围)。但是该教程展示了我的另一种方法。这是我的示例: 我有一个仅应为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
}

因此,仅根据MainActivityMasterActivity的理解,由于有了SecretKey模块,我将能够注入ContributesAndroidInjector类。因此SecretKey的范围在MainActivityMasterActivity之内。那么,为什么我们仍然能够使用Scope注释创建自定义范围?这是替代品吗?

1 个答案:

答案 0 :(得分:2)

Scope只是告诉Dagger 保存带有范围注释的对象的实例,而不是创建一个新对象。 Dagger会将实例保存在相应范围的组件中。 (您还应该知道@ContributesAndroidInjector为您代码生成了一个Subcomponent实例,因此,如果您使用范围注释对@ContributesAndroidInjector方法进行注释,则生成的子组件将采用该范围。)

在您的示例中,SecretKey没有作用域;每次您要求Dagger注入SecretKey时,它将调用您的构造函数并创建一个全新的实例。可能很好,因为SecretKey似乎不保持状态,并且保持实例 scopeless 可使垃圾收集器在不再需要它时收集SecretKey。

但是,假设您创建了自己的Cache对象,并且希望该Cache只要活动处于活动状态就可以生存,而不是更长的时间:每个新的Activity实例都应该拥有自己的Cache。与SecretKey不同,您无法在每次请求时都创建自己的Cache。您需要将缓存实例保存在某个地方。您可以选择在Activity本身上作为字段来执行此操作,也可以创建一个Module实例来在第一次调用@Provides方法时保存实例值,但是Dagger倾向于使用范围标记绑定与组件匹配的注释。这使您可以声明和记录绑定将与组件具有相同的生存期,并且可以轻松地将绑定归类为“应用程序范围”,“活动范围”,“片段范围”,“服务范围”等等。