android - 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>)
解决方案
推荐阅读
- c# - 如何停止和删除hangfire中的所有处理后台作业?
- javascript - 如何同时加载 magnific-popup 的“ajax 链接”和“ajax 链接页面内容”?
- python - 在 Python 中执行 http 请求的最快方法是什么
- matplotlib - height of colorbar in subplot (matplotlib)
- java - @cacheable 不适用于 Spring Boot。使用 ehcache3
- python - 当第二列包含 NaN/空字符串时,连接熊猫数据框中的两列而不在末尾添加额外的空格
- docker - 从 dockerfile 创建的目录在哪里,如何访问它?
- c# - 在 Android 和 IOS 上使用 MVVM Cross 显示 PDF 文件
- python-3.7 - 如何通过一个 html 请求更新多个对象?
- exception - 发现异常 - java.util.zip.ZipException:在 jmeter 中不是 GZIP 格式