Android 如果没有@Inject构造函数或@Provides注释构造函数,则无法提供ViewModel
问题已编辑 我正在向Android 如果没有@Inject构造函数或@Provides注释构造函数,则无法提供ViewModel,android,dagger-2,android-architecture-components,android-viewmodel,Android,Dagger 2,Android Architecture Components,Android Viewmodel,问题已编辑 我正在向BaseActivity注入ViewModelProvider.Factory,如下所示 open class BaseActivity : DaggerAppCompatActivity() { @Inject lateinit var factories: ViewModelProvider.Factory inline fun <reified T : ViewModel> getViewModel(): T {
BaseActivity
注入ViewModelProvider.Factory,如下所示
open class BaseActivity : DaggerAppCompatActivity() {
@Inject
lateinit var factories: ViewModelProvider.Factory
inline fun <reified T : ViewModel> getViewModel(): T {
return ViewModelProvider(this, factories).get(T::class.java)
}
}
为什么在我当前的实现中需要这个@Inject构造函数
class MainActivity : BaseActivity() {
private lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = getViewModel()
viewModel.showDialog()
}
}
App.kt
class App : DaggerApplication() {
override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
return DaggerAppComponent.builder().addContext(this).build()
}
}
@Component(
modules = [
AndroidInjectionModule::class,
AppModule::class,
ActivityBuilder::class,
ViewModelInjector::class
]
)
@Singleton
interface AppComponent : AndroidInjector<App> {
@Component.Builder
interface Builder {
fun addContext(@BindsInstance context: Context): Builder
fun build(): AppComponent
}
}
@Module
class AppModule {
@Provides
fun provideViewModelFactories(viewModels: Map<Class<out ViewModel>,
@JvmSuppressWildcards Provider<ViewModel>>):
ViewModelProvider.Factory {
return object : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
val factory = viewModels[modelClass]?.get() ?: error(
"No factory provided against ${modelClass.name}"
)
@Suppress("UNCHECKED_CAST")
return factory as T
}
}
}
}
@MapKey
@Retention(AnnotationRetention.SOURCE)
annotation class ViewModelKey(
val value: KClass<out ViewModel>
)
ViewModelInjector.kt
class App : DaggerApplication() {
override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
return DaggerAppComponent.builder().addContext(this).build()
}
}
@Component(
modules = [
AndroidInjectionModule::class,
AppModule::class,
ActivityBuilder::class,
ViewModelInjector::class
]
)
@Singleton
interface AppComponent : AndroidInjector<App> {
@Component.Builder
interface Builder {
fun addContext(@BindsInstance context: Context): Builder
fun build(): AppComponent
}
}
@Module
class AppModule {
@Provides
fun provideViewModelFactories(viewModels: Map<Class<out ViewModel>,
@JvmSuppressWildcards Provider<ViewModel>>):
ViewModelProvider.Factory {
return object : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
val factory = viewModels[modelClass]?.get() ?: error(
"No factory provided against ${modelClass.name}"
)
@Suppress("UNCHECKED_CAST")
return factory as T
}
}
}
}
@MapKey
@Retention(AnnotationRetention.SOURCE)
annotation class ViewModelKey(
val value: KClass<out ViewModel>
)
@模块
公共抽象类ViewModelInjector{
@Binds
@IntoMap
@ViewModelKey(MainViewModel.class)
public abstract ViewModel providesMainViewModel(MainViewModel model);
}
ViewModelKey.kt
class App : DaggerApplication() {
override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
return DaggerAppComponent.builder().addContext(this).build()
}
}
@Component(
modules = [
AndroidInjectionModule::class,
AppModule::class,
ActivityBuilder::class,
ViewModelInjector::class
]
)
@Singleton
interface AppComponent : AndroidInjector<App> {
@Component.Builder
interface Builder {
fun addContext(@BindsInstance context: Context): Builder
fun build(): AppComponent
}
}
@Module
class AppModule {
@Provides
fun provideViewModelFactories(viewModels: Map<Class<out ViewModel>,
@JvmSuppressWildcards Provider<ViewModel>>):
ViewModelProvider.Factory {
return object : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
val factory = viewModels[modelClass]?.get() ?: error(
"No factory provided against ${modelClass.name}"
)
@Suppress("UNCHECKED_CAST")
return factory as T
}
}
}
}
@MapKey
@Retention(AnnotationRetention.SOURCE)
annotation class ViewModelKey(
val value: KClass<out ViewModel>
)
@MapKey
@保留(AnnotationRetention.SOURCE)
注释类ViewModelKey(
val值:KClass
)
为什么我必须将@injectconstructor附加到每个ViewModel中,并请解释一下为什么我们需要@Binds@IntoMap,当你使用dagger android时,你应该将你的活动和片段作为DaggerActivity
(对于碎片,DaggerFragment
)
接下来,您应该为注入准备基础架构:
// All your injectors can be defined in this module
@Module(includes = [AndroidInjectionModule::class])
interface AppInjectorModule {
@ContributesAndroidInjector(modules = [MainActivityVmModule::class, /*other dependecies*/])
fun getMainActivityInjector(): MainActivity
}
@Module(includes = [VmFactoryModule::class])
abstract class MainActivityVmModule {
// bind implementation of ViewModel into map for ViewModelFactory
@Binds
@IntoMap
@ClassKey(MainViewModelImpl::class)
abstract fun bindMainVm(impl: MainViewModelImpl): ViewModel
@Module
companion object {
@Provides
@JvmStatic
fun getMainVm(activity: MainActivity, factory: ViewModelProvider.Factory): MainViewModel {
// create MainViewModelImpl in scope of MainActivity and inject dependecies by ViewModelFactory
return ViewModelProviders.of(activity, factory)[MainViewModelImpl::class.java]
}
}
}
工厂可提供不同的模块,以避免重复
@Module
interface VmFactoryModule {
@Binds
// bind your implementation of factory
fun bindVmFactory(impl: ViewModelFactory): ViewModelProvider.Factory
}
AppComponent
图形
@Component(
modules = [
AppInjectorModule::class
]
)
@Singleton
interface AppComponent : AndroidInjector<App>
@组件(
模块=[
AppInjectorModule::类
]
)
@独生子女
接口AppComponent:AndroidJector请解释MainActivityVmModule以及@Binds、IntoMap和ClassKey。为什么我们不在注入活动或片段中使用,而在为ViewModel添加注释。请看我更新的问题,它现在运行良好。但我的概念不正确clear@XarEAhmer使用@Binds
接近匕首时r创建依赖项(Vm)自动,但您应该在构造函数上设置注释@Inject
。您应该明确地说dagger应该使用哪个构造函数来创建Vm和注入依赖项。您还可以通过模块的方法使用@手动创建依赖项提供注释并通过setter设置依赖项(不推荐):@提供有趣的getVm(活动:活动,依赖项:VmDependency):ViewModel=ViewModelProviders.of(活动)[MainViewModelImpl::class.java]。应用{this.dependency=dependency}