I've been working on adapting code from the sunflower App tutorial, but it requires hilt to work now as well as using a @Provide annotation. I've added the annotations to the dao here below but now it is throwing this:
com/example/fittestapp/data/WorkoutDao.kt:16: [Hilt] Found unimplemented abstract methods, [getWorkouts(), getWorkout(java.lang.String), upsertAll(java.util.List<com.example.fittestapp.data.Workout>,kotlin.coroutines.Continuation<? super kotlin.Unit>)], in an abstract module, com.example.fittestapp.data.WorkoutDao. Did you forget to add a Dagger binding annotation (e.g. @Binds)? [1;31m[Hilt] Processing did not complete. See error above for details.[0m
import androidx.room.Dao
import androidx.room.Query
import androidx.room.Upsert
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ViewModelComponent
import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.flow.Flow
@Module
@InstallIn(SingletonComponent::class)
@Dao
interface WorkoutDao {
@Query("SELECT * FROM workouts ORDER BY title")
fun getWorkouts(): Flow<List<Workout>>
@Query("SELECT * FROM workouts WHERE id = :workoutId")
fun getWorkout(workoutId: String): Flow<Workout>
@Upsert
suspend fun upsertAll(workouts: List<Workout>)
}
I am not sure to understand what's happening here, if I add binds to the methods it throws another error
Here is the rest of the code:
@Singleton class WorkoutRepository @Inject constructor(
private val routineDao: RoutineDao
) {
suspend fun createRoutine(workoutId: String) {
val workoutRoutine = Routine(workoutId)
routineDao.insertRoutine(workoutRoutine)
}
suspend fun removeGardenPlanting(routine: Routine) {
routineDao.deleteRoutine(routine)
}
fun isSelected(workoutId: String) =
routineDao.isSelected(workoutId)
fun getRoutine() = routineDao.getSelectedRoutine()
companion object {
// For Singleton instantiation
@Volatile private var instance: WorkoutRepository? = null
fun getInstance(routineDao: RoutineDao) =
instance ?: synchronized(this) {
instance ?: WorkoutRepository(routineDao).also { instance = it }
}
}
}
@HiltViewModel
class WorkoutAndRoutineListViewModel @Inject internal constructor(
workoutRepository: WorkoutRepository
) : ViewModel() {
val workoutAndRoutineSelected : Flow<List<WorkoutAndRoutineSelected>> =
workoutRepository.getRoutine()
}
Thanks in advance
The issue is that you're trying to use your Dao interface as a Dagger module so the error occurs because the Dagger compiler is trying to process your Dao as a module.
You need to define the Room database as an abstract class
, which should have an abstract
method to access the Dao (which Room will create for you):
@Database(entities = [Workout::class], version = 1)
abstract class WorkoutDatabase : RoomDatabase() {
abstract fun workoutDao(): WorkoutDao
}
You could then create a Dagger module that creates the database instance and injects either the database or the Dao, something like this:
@InstallIn(SingletonComponent::class)
@Module
object DatabaseModule {
@Provides
@Singleton
fun provideWorkoutDatabase(@ApplicationContext context: Context): WorkoutDatabase =
Room.databaseBuilder(context, WorkoutDatabase::class.java, "workout-db")
.build()
@Provides
fun provideWorkoutDao(db: WorkoutDatabase): WorkoutDao = db.workoutDao()
}
Then you can inject it into your repository:
class WorkoutRepository @Inject constructor(private val workoutDao: WorkoutDao) {
...
}