Search code examples
androiddependency-injectionkoin

How to implement Koin dependency injection in Room MVVM Architecture


I'm following this documentation to implement koin dependency injection but it couldn't help me. I'm stuck in Modules.kt file I don't know how to pass DAO interface of Database to Repository constructor in module of koin.

UserEntity.kt

@Entity(tableName = "user_table")
data class UserEntity(...)

UserDao.kt

@Dao
interface UserDao { ... }

UserRepository.kt

class UserRepository(private val userDao: UserDao) {...}

UserViewModel.kt

class UserViewModel(private val repository: UserRepository) : ViewModel() {...}

UserDatabase.kt

@Database(
    entities = [UserEntity::class],
    version = 1,
    exportSchema = false
)
abstract class UserDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao

    companion object {

        @Volatile
        private var INSTANCE: UserDatabase? = null
        fun getDatabase(context: Context, scope: CoroutineScope): UserDatabase {
            return INSTANCE ?: synchronized(this) {
                val instance = Room.databaseBuilder(
                    context.applicationContext,
                    UserDatabase::class.java,
                    "user_data_database"
                ).build()
                INSTANCE = instance
                instance
            }
        }
    }
}

Modules.kt Here is Koin Modules

val appModule = module{

    single { UserRepository(get()) }

    viewModel { UserViewModel(get()) }

}

Solution

  • First of all in your class file which you extend from Room Database class. You will need to create an abstract function to provide Instance of your Dao Interface like this ,

    @Database(entities = [Run::class],version = 1 , exportSchema = false)
    abstract class RunningDatabase : RoomDatabase() {
    
    abstract fun getRunDao(): RunDao
    }
    

    Then in your module provide the Instance for Room Database like this,

    single {
       Room.databaseBuilder(
         androidApplication,
         RunningDatabase::class.java,
         RUNNING_DATABASE_NAME
     ).build()
    }
    

    Now you can call the abstract function of Room Database class to get the Instance of Dao Interface. Like this,

    single<RunningDao> {
      val database = get<RunningDatabase>()
      database.getRunDao()
    }
    

    Now you can pass this Interface in any constructor.