首页 > 解决方案 > Dagger2 为 Android 中的 ViewModel 提供 ApplicationContext

问题描述

我是 DI 新手,最近开始在我的项目中使用 dagger2。我能够为我的片段提供存储库并使用 ViewModelFactory,但我不知道如何将 ApplicationContext 提供到我的 ViewModel 中。我需要它来访问 SharePreferenceHelper 类。

这是我的 dagger2 实现:

我应该在哪里为 appContext 提供乐趣以及如何从 ViewModel 中注入它?

我知道这是一个很长的代码片段,但如果有人可以看一下,将不胜感激。

应用组件:

@Singleton
@Component(
    modules = [
        ApplicationModule::class,
        AndroidSupportInjectionModule::class,
        SettingsModule::class
    ]
)

interface ApplicationComponent : AndroidInjector<MyApplication> {

    @Component.Factory
    interface Factory {
        fun create(@BindsInstance applicationContext: Context): ApplicationComponent
    }

}

应用模块:

@Module
class ApplicationModule {

    @Singleton
    @Provides
    fun provideAssetsRepository(context: Context): AssetsRepository {
        return AssetsRepository(
            AppDatabase.getDatabase(context.applicationContext).assetDao()
        )
    }

    @Singleton
    @Provides
    fun provideExpensesRepository(context: Context): ExpensesRepository {
        return ExpensesRepository(
            AppDatabase.getDatabase(context.applicationContext).expenseDao()
        )
    }

    @Singleton
    @Provides
    fun provideTransactionsRepository(context: Context): TransactionsRepository {
        return TransactionsRepository(
            AppDatabase.getDatabase(context.applicationContext).transactionsDao()
        )
    }

}

我的应用程序:

open class MyApplication : DaggerApplication() {

    override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
        return DaggerApplicationComponent.factory().create(applicationContext)
    }

}

设置模块:

@Module
abstract class SettingsModule {

    @ContributesAndroidInjector(
        modules = [
            ViewModelBuilder::class]
    )

    internal abstract fun settingsFragment(): SettingsFragment

    @Binds
    @IntoMap
    @ViewModelKey(SettingsViewModel::class)
    internal abstract fun bindViewModel(viewModel: SettingsViewModel): ViewModel
}

视图模型工厂:

class ViewModelFactory @Inject constructor(
    private val creators: @JvmSuppressWildcards Map<Class<out ViewModel>, Provider<ViewModel>>
) : ViewModelProvider.Factory {
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        var creator: Provider<out ViewModel>? = creators[modelClass]
        if (creator == null) {
            for ((key, value) in creators) {
                if (modelClass.isAssignableFrom(key)) {
                    creator = value
                    break
                }
            }
        }
        if (creator == null) {
            throw IllegalArgumentException("Unknown model class: $modelClass")
        }
        try {
            return creator.get() as T
        } catch (e: Exception) {
            throw RuntimeException(e)
        }
    }
}

@Module
internal abstract class ViewModelBuilder {
    @Binds
    internal abstract fun bindViewModelFactory(
        factory: ViewModelFactory
    ): ViewModelProvider.Factory
}

@Target(
    AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER
)
@Retention(AnnotationRetention.RUNTIME)
@MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)

标签: androidkotlindependency-injectiondagger-2android-viewmodel

解决方案


推荐阅读