-1

I want to create multiple, separate databases of the same structure (all using the same RoomDatabase class and DAOs). I'm using Room DB and Hilt, and am using a provider like below to create the database:

@Singleton
@Provides
fun provideMyDatabase(@ApplicationContext context: Context): MyDatabase =
    Room
        .databaseBuilder(context, MyDatabase::class.java, name = dbName)
        .build()

The dbName is not known until runtime, and will be changed during the app. Even if this is possible, this feels like the wrong way to go about this but I'm not sure of any alternative. The number of DBs that will be created is dynamic, but all are of type MyDatabase (with a different dbName). Appreciate any thoughts in advance.

7
  • Please also edit to clarify how you provide dbName to Hilt. Where does it come from? How do you guarantee that it is available before Hilt starts the injection? Commented May 20 at 18:49
  • @tyg I added the context for the first thing you mentioned. For the second one, that is exactly what I am asking. I am not sure where it would come from, and am looking into how I could pass it in, or if there is a better method entirely to accomplish this. The dbName is not known until runtime, and will not be known until it is time to access the database. Commented May 20 at 19:58
  • You may be interested in stackoverflow.com/questions/69197676/… Commented May 20 at 20:11
  • @MikeT my app does do all of this now, however I'm (attempting) to migrate from manual DI to Hilt which is where I'm running into this problem Commented May 20 at 20:41
  • Well, you need to provide more context where dbName comes from. Please edit the question to provide an example of where dbName is calculated and where the actual database instance is needed. Commented May 20 at 23:09

1 Answer 1

2

So if I'm understanding correctly you just want two files that have the same database schema.
That shouldn't be too hard to achieve.

If you don't have any other dependencies you're not really getting the most bang for your buck with Hilt here.

basic use case

class DbFactory @Inject constructor(  
    @ApplicationContext context: Context  
) {  
  
    fun create(dbName: String): MyDatabase = Room  
        .databaseBuilder(context, MyDatabase::class.java, name = dbName)  
        .build()  
       
}  
  

With the above just inject the factory and use the same db name each time you want to get it out to read/write the data.

It only really gets fun if you want to inject extra things when creating the db. In which case you could consider something like @AssistedInject

https://dagger.dev/dev-guide/assisted-injection.html

In which case you'd just make a factory with some kind of method to pass in the db name.
Assuming you want some kind of Repository style wrapper around the db to run insert/queries on you could do something along these lines...

@AssistedFactory  
interface MyRepositoryLogicFactory {  
  create(name: String): MyRepositoryLogic  
}  

class MyRepositoryLogic @AssistedInject constructor(  
    @ApplicationContext context: Context,  
    dependencyA: DependencyA,  
    dependencyB: DependencyB,  
    @Assisted dbName: String  
    //add any other injected dependencies here  
) {  

private val db = Room
        .databaseBuilder(context, MyDatabase::class.java, name = dbName)
        .build()

//...do whatever with the db in here..
}  

same rules apply as the first example. you'd inject the factory into whatever needs rather than the db, and use the same dbName each time you want to generate an instance to do things against.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.