Я новичок в кинжале и хочу использовать его для введения ViewModels (наряду с другими объектами, такими как репозитории). Когда я пытаюсь скомпилировать приложение, появляется эта ошибка:
e: C:\Project\...\app\build\tmp\kapt3\stubs\debug\com\myapp\di\AppComponent.java:16: error: [Dagger/MissingBinding] java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> cannot be provided without an @Provides-annotated method.
public abstract interface AppComponent {
^
java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> is injected at
com.myapp.di.ViewModelFactory(viewModels)
com.myapp.di.ViewModelFactory is injected at
com.myapp.di.ViewModelModule.bindViewModelFactory(factory)
androidx.lifecycle.ViewModelProvider.Factory is injected at
com.myapp.ui.activity.MainActivity.viewModelFactory
com.myapp.ui.activity.MainActivity is injected at
dagger.android.AndroidInjector.inject(T) [com.myapp.di.AppComponent ? com.myapp.di.ActivityModule_ContributeMainActivity.MainActivitySubcomponent]
The following other entry points also depend on it:
dagger.android.AndroidInjector.inject(T) [com.myapp.di.AppComponent ? com.myapp.di.ActivityModule_ContributeItemsFrament.ItemsFragmentSubcomponent]
Возможно, есть одна глупая ошибка, которая мешает компиляции.
Компонент кинжала:
@Singleton
@Component(modules = [AndroidSupportInjectionModule::class, AppModule::class, DatabaseModule::class, ViewModelModule::class, ActivityModule::class])
interface AppComponent {
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: MyCustomApplication): Builder
fun build(): AppComponent
}
fun inject(app: MyCustomApplication)
}
AppModule:
@Module
class AppModule {
@Inject
lateinit var app: Application
@Provides
@Singleton
fun provideAppContext(): Context = app.applicationContext
}
ActivityModule:
@Module
abstract class ActivityModule {
@ContributesAndroidInjector
abstract fun bindMainActivity(): MainActivity
@ContributesAndroidInjector
abstract fun contributeMainFrament(): MainFragment
}
ViewModelModule:
@Module
abstract class ViewModelModule {
@Binds
abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory
@Binds
@IntoMap
@ViewModelKey(MainViewModel::class)
abstract fun mainViewModel(mainViewModel: MainViewModel): ViewModel
}
ViewModelFactory:
@Singleton
class ViewModelFactory
@Inject constructor(private val viewModels: MutableMap<Class<out ViewModel>, Provider<ViewModel>>)
: ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
val creator = viewModels[modelClass]
?: viewModels.asIterable().firstOrNull { modelClass.isAssignableFrom(it.key) }?.value
?: throw IllegalArgumentException("unknown model class $modelClass")
return try {
creator.get() as T
} catch (e: Exception) {
throw RuntimeException(e)
}
}
}
Класс приложения:
class MyCustomApplication : Application(), HasActivityInjector, HasSupportFragmentInjector {
@Inject lateinit var activityInjector: DispatchingAndroidInjector<Activity>
override fun onCreate() {
super.onCreate()
DaggerMainComponent
.builder()
.application(this)
.build()
.inject(this)
}
override fun activityInjector() = activityInjector
}
MainViewModel ( обратите внимание, что он расширяется от AndroidViewModel
и требует контекст приложения ):
class MainViewModel @Inject constructor(app: Application, private val repository: MainRepository)
: AndroidViewModel(app) {
MainActivity:
class MainActivity : BaseActivity() {
@Inject
internal lateinit var viewModelFactory: ViewModelProvider.Factory
private lateinit var viewModel: MainViewModel
override fun onCreate(savedState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedState)
viewModel = ViewModelProviders.of(this,viewModelFactory).get(MainViewModel::class.java)