codinginflow / MVVMTodo

187 stars 124 forks source link

error: [Dagger/MissingBinding] @com.calamity.weather.di.ApplicationScope kotlinx.coroutines.CoroutineScope cannot be provided without an @Provides-annotated method. #6

Closed CalamityDeadshot closed 3 years ago

CalamityDeadshot commented 3 years ago

I was following along the tutorial and ran into a build error.

Complete error log:

C:\Users\semyo\AndroidStudioProjects\Weather\app\build\generated\source\kapt\debug\com\calamity\weather\utils\WeatherApplication_HiltComponents.java:135: error: [Dagger/MissingBinding] @com.calamity.weather.di.ApplicationScope kotlinx.coroutines.CoroutineScope cannot be provided without an @Provides-annotated method.
  public abstract static class SingletonC implements WeatherApplication_GeneratedInjector,
                         ^
      @com.calamity.weather.di.ApplicationScope kotlinx.coroutines.CoroutineScope is injected at
          com.calamity.weather.data.database.WeatherDatabase.Callback(�, applicationScope)
      com.calamity.weather.data.database.WeatherDatabase.Callback is injected at
          com.calamity.weather.di.AppModule.provideDatabase(�, callback)
      com.calamity.weather.data.database.WeatherDatabase is injected at
          com.calamity.weather.di.AppModule.provideWeatherDao(db)
      javax.inject.Provider<com.calamity.weather.data.dao.WeatherDao> is injected at
          com.calamity.weather.ui.detailedweather.WeatherViewModel_AssistedFactory(weatherDao)
      com.calamity.weather.ui.detailedweather.WeatherViewModel_AssistedFactory is injected at
          com.calamity.weather.ui.detailedweather.WeatherViewModel_HiltModule.bind(factory)
      java.util.Map<java.lang.String,javax.inject.Provider<androidx.hilt.lifecycle.ViewModelAssistedFactory<? extends androidx.lifecycle.ViewModel>>> is injected at
          androidx.hilt.lifecycle.ViewModelFactoryModules.ActivityModule.provideFactory(�, viewModelFactories)
      @dagger.hilt.android.internal.lifecycle.DefaultActivityViewModelFactory java.util.Set<androidx.lifecycle.ViewModelProvider.Factory> is injected at
          dagger.hilt.android.internal.lifecycle.DefaultViewModelFactories.InternalFactoryFactory(�, defaultActivityFactorySet, �)
      dagger.hilt.android.internal.lifecycle.DefaultViewModelFactories.InternalFactoryFactory is requested at
          dagger.hilt.android.internal.lifecycle.DefaultViewModelFactories.ActivityEntryPoint.getHiltInternalFactoryFactory() [com.calamity.weather.utils.WeatherApplication_HiltComponents.SingletonC ? com.calamity.weather.utils.WeatherApplication_HiltComponents.ActivityRetainedC ? com.calamity.weather.utils.WeatherApplication_HiltComponents.ActivityC]
  The following other entry points also depend on it:
      dagger.hilt.android.internal.lifecycle.DefaultViewModelFactories.FragmentEntryPoint.getHiltInternalFactoryFactory() [com.calamity.weather.utils.WeatherApplication_HiltComponents.SingletonC ? com.calamity.weather.utils.WeatherApplication_HiltComponents.ActivityRetainedC ? com.calamity.weather.utils.WeatherApplication_HiltComponents.ActivityC ? com.calamity.weather.utils.WeatherApplication_HiltComponents.FragmentC][WARN] Incremental annotation processing requested, but support is disabled because the following processors are not incremental: androidx.room.RoomProcessor (DYNAMIC).

My application does something different from that of the tutorial, but I was just trying to build a structure for it.

My AppModule (I'm using SingletonComponent::class because ApplicationComponent::class was deprecated. I tried an earlier version of Hilt, but it doesn't work anyway):

package com.calamity.weather.di

import android.app.Application
import androidx.room.Room
import com.calamity.weather.data.database.WeatherDatabase
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
import javax.inject.Qualifier
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object AppModule {
    @Provides
    @Singleton
    fun provideDatabase(
        app: Application,
        callback: WeatherDatabase.Callback
    ) = Room.databaseBuilder(app, WeatherDatabase::class.java, "weather_database")
            .fallbackToDestructiveMigration()
            .addCallback(callback)
            .build()

    @Provides
    fun provideWeatherDao(db: WeatherDatabase) = db.weatherDao()
    @Provides
    fun provideCurrentWeatherDao(db: WeatherDatabase) = db.currentWeatherDao()

    @Provides
    @Singleton
    fun providesApplicationScope() = CoroutineScope(SupervisorJob())

}

@Retention(AnnotationRetention.RUNTIME)
@Qualifier
annotation class ApplicationScope

My Database:

package com.calamity.weather.data.database

import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import androidx.sqlite.db.SupportSQLiteDatabase
import com.calamity.weather.data.api.CurrentWeather
import com.calamity.weather.data.api.Weather
import com.calamity.weather.data.api.subclasses.*
import com.calamity.weather.data.dao.CurrentWeatherDao
import com.calamity.weather.data.dao.WeatherDao
import com.calamity.weather.di.ApplicationScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import javax.inject.Inject
import javax.inject.Provider

@Database(entities = [CurrentWeather::class, Weather::class], version = 1)
@TypeConverters(Converters::class)
abstract class WeatherDatabase : RoomDatabase() {

    abstract fun weatherDao(): WeatherDao
    abstract fun currentWeatherDao(): CurrentWeatherDao

    class Callback @Inject constructor(
        private val database: Provider<WeatherDatabase>,
        @ApplicationScope private val applicationScope: CoroutineScope
    ) : RoomDatabase.Callback() {

        // First db initialization, todo: implement gps
        override fun onCreate(db: SupportSQLiteDatabase) {
            super.onCreate(db)

            val dao = database.get().currentWeatherDao()

            applicationScope.launch {
                dao.insert(/* */)
            }
        }
    }
}

What might be the case here and how can I fix it?

CalamityDeadshot commented 3 years ago

Ok, I made a stupid mistake of forgetting to add an @ApplicationScope annotation. Sorry