2

I can't inject my viewModel properly can I please get some help ? I keep getting

ViewModel cannot be provided without an @Inject constructor or an @Provides-annotated method.

Here is my code

    @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
    }
}

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()
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

    }

}

class ExcitelApplication : DaggerApplication() {

    @Inject
    lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>
    override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
        return DaggerApplicationComponent.builder().application(this).bindContext(this).build()
    }
}

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()
    }
}

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()
    }
}

class ExcitelViewModelFactory @Inject constructor( private val viewModel: Lazy ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun <T : ViewModel?> create(modelClass: Class): T = viewModel.get() as T }

Any idea how can I resolve it ? I had it working the same way in a different project but in this new one I keep getting this error :

error: [Dagger/MissingBinding] com.example.excitelassignment.countrylist.presentation.viewmodel.CountriesViewModel cannot be provided without an @Inject constructor or an @Provides-annotated method. public abstract interface ApplicationComponent extends dagger.android.AndroidInjector<com.example.excitelassignment.application.ExcitelApplication> {

Mitashkin
  • 21
  • 2
  • What does the ViewModelFactory look like? – TheLibrarian Oct 18 '22 at 09:44
  • `class ExcitelViewModelFactory @Inject constructor( private val viewModel: Lazy ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create(modelClass: Class): T = viewModel.get() as T }` – Mitashkin Oct 18 '22 at 15:16
  • Next time, you can edit the question. You are not providing the view model anywhere. All the factory does is it takes the view model and casts it to the T. – TheLibrarian Oct 18 '22 at 15:41

0 Answers0