11

When I use interface like below in viewmodel

class MainViewModel @ViewModelInject constructor(
    private val trafficImagesRepository: TrafficImageRepository, <----------------- Not working
    @Assisted private val savedStateHandle: SavedStateHandle
) : ViewModel() 

I am getting an error like below

cannot be provided without an @Provides-annotated method.
  public abstract static class SingletonC implements MainApplication_GeneratedInjector,

My interface is like below

interface TrafficImageRepository {
    suspend fun getTrafficImages() : NetworkResponse<TrafficData, ErrorTrafficImages>
}

And Repository class is like below

class DefaultTrafficImagesRepository @Inject constructor(private val trafficImageService: TrafficImageService) : TrafficImageRepository {

    override suspend fun getTrafficImages(): NetworkResponse<TrafficData, ErrorTrafficImages> {
        lateinit var response: NetworkResponse<TrafficData, ErrorTrafficImages>
        withContext(IO) {
            val currentTimestamp = Constants.getCurrentTime()
            response = trafficImageService.getTrafficImages(currentTimestamp)
        }
        return response
    }
}

But when I use DefaultTrafficImagesRepository class directly instead of Interface my app is able to build without any error.

class MainViewModel @ViewModelInject constructor(
    private val trafficImagesRepository: DefaultTrafficImagesRepository , <----------------- Working Fine
    @Assisted private val savedStateHandle: SavedStateHandle
) : ViewModel()
Siddhpura Amit
  • 14,534
  • 16
  • 91
  • 150

3 Answers3

12

You must to bind interface

@Module
@InstallIn(ViewModelComponent::class)
abstract class RepositoryModule {

    @Binds
    abstract fun bindRepository(impl: DefaultTrafficImagesRepository): TrafficImageRepository 
}

and use viewmodel inject in this way

@HiltViewModel
class MainViewModel @Inject constructor(
    private val trafficImagesRepository: TrafficImageRepository,
    @Assisted private val savedStateHandle: SavedStateHandle
) : ViewModel() 
Saeid Lotfi
  • 2,043
  • 1
  • 11
  • 23
0

Better late than never. Besides you need do the thing mentioned in the accepted answer.If you are working with compose or the latest Hilt version, init your ViewModel by the way of: val viewModel: YourViewModel by viewModels() do not use the way of: @Inject lateinit var viewModel: YourViewModel

Jun Du
  • 29
  • 4
0

Just to add to this post in case anyone needs it in the future, it's important to, as Jun Du mentioned, to init your ViewModel as val viewModel: YourViewModel by viewModels() or val viewModel by viewModels<YourViewModel>() because the method viewModels creates, under the hood, the factory that your viewModel needs to receive the injected dependencies in your constructor. For that, you need the Android KTX extension as exemplified in this Android Hilt doc