Android Room with Dagger 2 in a multi-module

1.3k views Asked by At

Is there a way or approach to provide a Room DB instance from a module/library which can be consume on any project (app module)?

The problem I am facing is the abstract class that extends RoomDatabase() lies in our app module and there we define our entities using @Database annotation. This is the reason I cannot provide a Room instance coming from a module other than app module since creating Room instance requires you to define the app database class that extends the RoomDataBase().

Example in my :app:libs:common module. This is a submodule, it has its own repository which can be use for any project. The appName is provided in the AppModule which resides in app module itself and it is working with SharedPreferences that I made.

 @Module
 CommonModule {
    
    @Provides
    @Singleton
    fun provideSharedPreferencesInstance(
        @Named("AppName") appName: String,
        application: Application
    ): SharedPreferences {
        application.apply {
            return getSharedPreferences(appName, MODE_PRIVATE)
        }
    }

    @Provides
    @Singleton
    fun provideAppSharedPrefImplInstance(
        sharedPreferences: SharedPreferences
    ): SharedPref = SharedPrefImpl(sharedPreferences)

    @Provides
    @Singleton
    fun provideRoomDatabaseInstance(
            application: Application,
            @Named("AppName") appName: String,
            @Named("AppDatabase") roomDatabase: RoomDatabase
        ): RoomDatabase {
            return Room
                .databaseBuilder(application, roomDatabase.javaClass, appName)
                .fallbackToDestructiveMigration()
                .build()
        }
    
}

This is the app module.

@Module
object AppModule {
    @Provides
    @Singleton
    @Named("AppName")
    fun provideAppName(application: Application): String {
        application.apply {
            return getString(R.string.app_name)
        }
    }

    @Provides
    @Singleton
    fun provideAssetDao(@Named("AppDatabase") db: AppDatabase): AssetDao {
        return db.assetDao
    }
}

Since we use abstract class when extending RoomDatabase() in this case it's AppDatabase I tried to use @Binds in hope that it will work.

@Module
abstract class RoomModule {

    @Binds
    @Singleton
    @Named("AppDatabase")
    abstract fun bindAppDatabase(appDatabase: AppDatabase): AppDatabase

}

I think being able to provide the AppDatabase class via generic on common module will allow me to fix this issue

1

There are 1 answers

2
LuongXuanNam On

I have encountered this case. I have written a boilerplate for using multiple modules in an Android project, it contains the room database. You can refer to my repos My Repo

Hope this is helpful to you