https://kotlinlang.org logo
#kodein
Title
j

Joan Colmenero

07/06/2019, 7:14 PM
Copy code
@Database(entities = [Something::class], version = 1, exportSchema = false)
abstract class MyDatabase : RoomDatabase() {

    abstract fun myDao(): MyDao

    companion object {

        @Volatile
        private var INSTANCE: MyDatabase? = null

        fun getInstance(context: Context): MyDatabase =
            INSTANCE ?: synchronized(this) {
                INSTANCE ?: buildDatabase(context).also { INSTANCE = it }
            }

        private fun buildDatabase(context: Context) =
            Room.databaseBuilder(
                context.applicationContext,
                MyDatabase::class.java, "sample_db"
            )
                .allowMainThreadQueries()
                .build()
    }

}
s

salomonbrys

07/06/2019, 7:23 PM
Can you be more specific about what you are trying to achieve ?
s

streetsofboston

07/06/2019, 7:25 PM
First, is is
MyDatabase
or
BrewDatabase
? Let's assume it is
BrewDatabase
. Remove the
companion object
stuff. Then have a module with a binding, or just a binding, that is something like this
Copy code
bind<BrewDatabase>() with singleton { Room.databaseBuilder(instance(), BrewDatabase::class.java, "sample_db").allowMainThreadQueries().build() }
All the rest is annotation driven and kodein, or any other DI/SL, cannot help here
j

Joan Colmenero

07/06/2019, 7:34 PM
I want to DI this MyDatabase object, like I'm doing with all my Presenter, Activity, etc... but now I never did it before, so I want to call for instance this MyDao from everywhere on my APP, because now I'm doing MyDatabase.myDao.anyMethod() and I want to achieve something like I'm doing with my Repository or Usecase that I have a service as a parameter and I can use them, so I don't know the way to move this into DI so I can use it from any other class instead of doing always MyDatabase.getInstance(this).myDao.someMethod
Is it clear?
@streetsofboston don't get what you are trying to say with
All the rest is annotation driven and kodein, or any other DI/SL, cannot help here
s

streetsofboston

07/06/2019, 7:39 PM
The annotation creates source code, a class that is a subclass of MyDatabase (or BrewDatabase?). The call to Room.databaseBuilder...... will return you an instance of that subclass.
j

Joan Colmenero

07/06/2019, 7:41 PM
Yes, my question is, can I avoid using MyDatabase.getInstance(this).myDao().insertUser(someUser) eveytime? I mean avoid this :
MyDatabase.getInstance(this).myDao()
s

streetsofboston

07/06/2019, 7:42 PM
The you can do
val myDb: MyDatabase by kodein.instance()
just like any other kodein dependency
Also, is it MyDatabase or BrewDatabase?
Ah... You corrected it, it's MyDatabase 😀
And then you can use
myDb.myDao()
etc
j

Joan Colmenero

07/06/2019, 7:45 PM
So I don't have to create a module for this
As I'm doing with the rest of my stuff?
s

streetsofboston

07/06/2019, 7:45 PM
You could. It depends. Modules are just for your own organization of the code.
j

Joan Colmenero

07/06/2019, 7:46 PM
Ahhh, Yes, sorry so I can create a module called databaseModule and inside put something like bind<MyDatabase>() with singleton { Room.databaseBuilder( context.applicationContext, MyDatabase::class.java, "sample_db" ) .allowMainThreadQueries() .build() }
Is that correct?
So, I have to remove all of the companionObject thing? right?
s

streetsofboston

07/06/2019, 7:49 PM
Yup, exactly. You can even make the context.applicationContext a dependency (from another module) on which this dependency depends. 😀
Yup, either use the kodein stuff or use the companion object construct.
j

Joan Colmenero

07/06/2019, 7:50 PM
Oh, true, I need the context
But how do I create a Bind for the context?
Should be something like this : https://github.com/Kodein-Framework/Kodein-DI/issues/32#issuecomment-242915281, but I'm not getting app as a parameter I have this
Copy code
val contextModule = Kodein.Module("contextModule") {

    bind<Context>() with instance()

}
s

streetsofboston

07/06/2019, 7:59 PM
That looks recursive, the above code snippet.
bind<MyApplication> with singleton { MyApplication.INSTANCE }
And MyApplication is your Application subclass, which is a Context subclass as well. Be sure to get the dependency (in your Database Module) using
instance<MyApplication>()
though.
j

Joan Colmenero

07/06/2019, 7:59 PM
@salomonbrys You know about it? How can I bind the context? So I can use to create the Room.databaseBuilder(context.applicationContext...) ?
r

romainbsl

07/09/2019, 7:35 AM
You could also use a factory, and passing the context to retrieve the right instance, like:
Copy code
// Binding
bind<Database>() with factory { ctx -> Room.databaseBuilder(ctx) }
// Retrieving
val db: Database by kodein.instance(arg = context)
4 Views