I have a problem with the dagger injection when I am rebuilding the project. I recently started learning dagger 2 and I encountered this error, can anyone help me? I spent a lot of time on it, your answer will help me a lot.
[Dagger/MissingBinding] com.example.weatherforecast_rxjava_mvvm_dagger2.data.api.interceptors.LoggingInterceptor cannot be provided without an @Inject constructor or an @Provides-annotated method.
public abstract interface AppComponent {
^
Missing binding usage:
com.example.weatherforecast_rxjava_mvvm_dagger2.data.api.interceptors.LoggingInterceptor is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.di.AppModule.provideLoggingInterceptor(loggingInterceptor)
okhttp3.logging.HttpLoggingInterceptor is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.di.AppModule.provideOkHttp(loggingInterceptor)
okhttp3.OkHttpClient is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.di.AppModule.provideRetrofit(okHttp)
retrofit2.Retrofit.Builder is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.di.AppModule.provideApi(builder)
com.example.weatherforecast_rxjava_mvvm_dagger2.data.api.WeatherApi is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.data.repository.WeatherRepositoryImpl(weatherApi, �)
com.example.weatherforecast_rxjava_mvvm_dagger2.data.repository.WeatherRepositoryImpl is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.di.RepositoryModule.bindRepository(repository)
com.example.weatherforecast_rxjava_mvvm_dagger2.domain.repository.WeatherRepository is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.ui.WeatherViewModel(repository, �)
com.example.weatherforecast_rxjava_mvvm_dagger2.ui.WeatherViewModel is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.di.ViewModelModule.bindViewModel(viewModel)
java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.ui.ViewModelFactory(creators)
com.example.weatherforecast_rxjava_mvvm_dagger2.ui.ViewModelFactory is requested at
com.example.weatherforecast_rxjava_mvvm_dagger2.di.AppComponent.viewModelFactory()
The following other entry points also depend on it:
com.example.weatherforecast_rxjava_mvvm_dagger2.di.AppComponent.inject(com.example.weatherforecast_rxjava_mvvm_dagger2.MainActivity)
[Dagger/MissingBinding] android.app.Application cannot be provided without an @Inject constructor or an @Provides-annotated method.
public abstract interface AppComponent {
^
Missing binding usage:
android.app.Application is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.data.location.LocationTrackerImpl(�, application)
com.example.weatherforecast_rxjava_mvvm_dagger2.data.location.LocationTrackerImpl is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.di.LocationModule.bindLocationTracker(locationTracker)
com.example.weatherforecast_rxjava_mvvm_dagger2.domain.location.LocationTracker is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.ui.WeatherViewModel(�, locationTracker)
com.example.weatherforecast_rxjava_mvvm_dagger2.ui.WeatherViewModel is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.di.ViewModelModule.bindViewModel(viewModel)
java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.ui.ViewModelFactory(creators)
com.example.weatherforecast_rxjava_mvvm_dagger2.ui.ViewModelFactory is requested at
com.example.weatherforecast_rxjava_mvvm_dagger2.di.AppComponent.viewModelFactory()
It is also requested at:
com.example.weatherforecast_rxjava_mvvm_dagger2.di.AppModule.provideFusedLocationProviderClient(app)
The following other entry points also depend on it:
com.example.weatherforecast_rxjava_mvvm_dagger2.di.AppComponent.inject(com.example.weatherforecast_rxjava_mvvm_dagger2.MainActivity)
Below are my classes:
AppComponent
@Singleton
@Component(modules = [AppModule::class, LocationModule::class, RepositoryModule::class, ViewModelModule::class])
interface AppComponent {
fun inject(mainActivity: MainActivity)
fun viewModelFactory(): ViewModelFactory
}
AppModule
@Module
object AppModule {
@Provides
@Singleton
fun provideApi(builder: Retrofit.Builder): WeatherApi {
return builder
.build()
.create(WeatherApi::class.java)
}
@Provides
@Singleton
fun provideRetrofit(okHttp: OkHttpClient): Retrofit.Builder {
return Retrofit.Builder()
.baseUrl(ApiConstants.API_BASE_URL)
.client(okHttp)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
}
@Provides
@Singleton
fun provideOkHttp(loggingInterceptor: HttpLoggingInterceptor): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.build()
}
@Provides
@Singleton
fun provideLoggingInterceptor(loggingInterceptor: LoggingInterceptor): HttpLoggingInterceptor {
val httpLoggingInterceptor = HttpLoggingInterceptor(loggingInterceptor)
httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
return httpLoggingInterceptor
}
@Provides
@Singleton
fun provideFusedLocationProviderClient(app: Application): FusedLocationProviderClient {
return LocationServices.getFusedLocationProviderClient(app)
}
}
LocationModule
@Module
interface LocationModule {
@Binds
@Singleton
fun bindLocationTracker(locationTracker: LocationTrackerImpl): LocationTracker
}
RepositoryModule
@Module
interface RepositoryModule {
@Binds
@Singleton
fun bindRepository(repository: WeatherRepositoryImpl): WeatherRepository
}
ViewModelKey
@MustBeDocumented
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
@MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)
ViewModelFactory
@Suppress("UNCHECKED_CAST")
@Singleton
class ViewModelFactory @Inject
constructor(
private val creators: Map<Class<out ViewModel>,
@JvmSuppressWildcards Provider<ViewModel>>
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
var creator: Provider<out ViewModel>? = creators[modelClass]
if (creator == null) {
for ((key, value) in creators) {
if (modelClass.isAssignableFrom(key)) {
creator = value
break
}
}
}
if (creator == null) {
throw IllegalArgumentException("unknown model class " + modelClass)
}
try {
return creator.get() as T
} catch (e: Exception) {
throw RuntimeException(e)
}
}
}
WeatherViewModel
class WeatherViewModel @Inject constructor(
private val repository: WeatherRepository,
private val locationTracker: LocationTracker
): ViewModel() {
private val disposables = CompositeDisposable()
private var _state = MutableStateFlow(WeatherState())
val state = _state.asStateFlow()
override fun onCleared() {
disposables.dispose()
super.onCleared()
}
init {
locationTracker.getCurrentLocation().subscribe(object : SingleObserver<Location?> {
override fun onSubscribe(d: Disposable) {
disposables.add(d)
}
override fun onError(e: Throwable) {
_state.value.weather = State.Error(e.message.orEmpty())
}
override fun onSuccess(location: Location) {
location.let {
repository.getWeatherData(it.latitude, it.longitude).subscribe(object : SingleObserver<State<Weather>> {
override fun onSubscribe(d: Disposable) {
disposables.add(d)
}
override fun onError(e: Throwable) {
_state.value.weather = State.Error(e.message.orEmpty())
}
override fun onSuccess(weatherState: State<Weather>) {
_state.value.weather = weatherState
}
})
}
}
})
}
}
WeatherApp
class WeatherApp: Application() {
lateinit var appComponent: AppComponent
override fun onCreate() {
super.onCreate()
appComponent = DaggerAppComponent.builder().build()
}
}
val Context.appComponent: AppComponent
get() = when (this) {
is WeatherApp -> appComponent
else -> this.applicationContext.appComponent
}
MainActivity
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var permissionLauncher: ActivityResultLauncher<Array<String>>
@Inject
lateinit var viewModelFactory: ViewModelFactory
private lateinit var viewModel: WeatherViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
appComponent.inject(this)
permissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) {}
permissionLauncher.launch(arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
))
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
viewModel = ViewModelProvider(this, viewModelFactory)[WeatherViewModel::class.java]
when(val weatherState = viewModel.state.value.weather) {
is State.Loading -> {
TODO()
}
is State.Success -> {
TODO()
}
is State.Error -> {
TODO()
}
}
}
}
I have tried to google it but nothing there worked
Your errors say that you are trying to use some objects which you have not provided to a dependency graph.
In your AppModule you need to provide an instance of LoggingInterceptor to use it for creating HttpLoggingInterceptor. Add this function after provideLoggingInterceptor
@Provides
@Singleton
fun provideLoggingInterceptorImpl(): LoggingInterceptor {
// return LoggingInterceptor()
}
Or remove loggingInterceptor parameter from provideLoggingInterceptor function.
Looks like your LocationTrackerImpl is injected with an Application. Add these lines into your AppComponent and create it with the Builder, providing Application to the graph:
@Component.Builder
interface Builder {
fun build(): AppComponent
@BindsInstance
fun app(app: Application): Builder
}
then, where the AppComponent is created:
val appComponent = DaggerAppComponent.builder().app(this).build()