Dagger注入ViewModel失败:MissingBinding错误求助
解决Dagger注入ViewModel时的MissingBinding错误
问题描述
注入CountriesViewModel时持续报错,即便已给ViewModel添加@Inject构造函数,仍收到以下提示:
error: [Dagger/MissingBinding] com.example.excitelassignment.countrylist.presentation.viewmodel.CountriesViewModel cannot be provided without an @Inject constructor or an @Provides-annotated method.
中文翻译:[Dagger/缺失绑定] 无法提供com.example.excitelassignment.countrylist.presentation.viewmodel.CountriesViewModel,需添加@Inject构造函数或@Provides注解方法。
相关代码
ApplicationComponent
@Singleton @Component(modules = [AndroidInjectionModule::class, ActivityBuilderModule::class, FragmentBuilderModule::class, BaseNetworkModule::class, CountriesListApiModule::class]) interface ApplicationComponent : AndroidInjector<ExcitelApplication> { @Component.Builder interface Builder { @BindsInstance fun application(application: Application): Builder @BindsInstance fun bindContext(context: Context): Builder fun build(): ApplicationComponent } }
CountriesListFragment
class CountriesListFragment : Fragment(R.layout.countries_fragment) { @Inject lateinit var viewModelFactory: ExcitelViewModelFactory<CountriesViewModel> lateinit var countriesViewModel: CountriesViewModel override fun onAttach(context: Context) { AndroidSupportInjection.inject(this) super.onAttach(context) } override fun onActivityCreated(savedInstanceState: Bundle?) { countriesViewModel = ViewModelProvider(this, viewModelFactory)[CountriesViewModel::class.java] countriesViewModel.getCountries() } }
ExcitelApplication
class ExcitelApplication : DaggerApplication() { @Inject lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any> override fun applicationInjector(): AndroidInjector<out DaggerApplication> { return DaggerApplicationComponent.builder().application(this).bindContext(this).build() } }
CountryListActivity
class CountryListActivity: BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { AndroidInjection.inject(this); super.onCreate(savedInstanceState) setContentView(R.layout.countries_activity) replaceFragment(CountriesListFragment()) } open fun replaceFragment(fragment: Fragment) { val fragmentManager: FragmentManager = supportFragmentManager val fragmentTransaction: FragmentTransaction = fragmentManager.beginTransaction() fragmentTransaction.add(R.id.container, fragment) fragmentTransaction.addToBackStack(fragment.toString()) fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) fragmentTransaction.commit() } }
CountriesViewModel
class CountriesViewModel @Inject constructor( private val countriesUseCase: CountriesUseCaseImpl ) : ViewModel() { val countriesLiveData = MutableLiveData<Resource<CountriesResult>>() private val compositeDisposable = CompositeDisposable() fun getCountries() { val countriesDisposable = countriesUseCase.getCountries() .doOnSubscribe { countriesLiveData.value = Resource.Loading() } .subscribe( { success -> countriesLiveData.postValue(Resource.Success(success)) }, { throwable -> countriesLiveData.postValue(Resource.Failure(throwable)) } ) compositeDisposable.add(countriesDisposable) } override fun onCleared() { super.onCleared() compositeDisposable.clear() } }
ExcitelViewModelFactory
class ExcitelViewModelFactory @Inject constructor(private val viewModel: Lazy<CountriesViewModel>) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun <T : ViewModel?> create(modelClass: Class<T>): T = viewModel.get() as T }
解决方案
- 检查CountriesUseCaseImpl的依赖配置:ViewModel构造依赖该类,必须确保它要么有
@Inject注解的构造函数,要么在某个Dagger模块中通过@Provides方法提供实例。若该依赖无法被Dagger创建,会间接导致ViewModel无法注入,触发MissingBinding错误。 - 验证FragmentBuilderModule的配置:确保模块中用
@ContributesAndroidInjector注解CountriesListFragment,让Dagger知晓如何注入该Fragment。示例配置:@Module abstract class FragmentBuilderModule { @ContributesAndroidInjector abstract fun contributeCountriesListFragment(): CountriesListFragment } - 优化ViewModelFactory为通用实现:当前Factory硬编码针对CountriesViewModel,改成通用版本可避免泛型识别问题,示例:
class ExcitelViewModelFactory @Inject constructor( private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>> ) : ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>): T { val creator = creators[modelClass] ?: creators.entries.firstOrNull { modelClass.isAssignableFrom(it.key) }?.value ?: throw IllegalArgumentException("Unknown model class $modelClass") try { @Suppress("UNCHECKED_CAST") return creator.get() as T } catch (e: Exception) { throw RuntimeException(e) } } } - 清理重建项目:Dagger注解处理器缓存可能引发异常,执行Android Studio中的
Clean Project和Rebuild Project操作,重新生成Dagger注入代码。
内容的提问来源于stack exchange,提问作者Mitashkin
相关产品推荐
相关产品推荐

