Where to put the variable holding the Room database?

Viewed 79

In my main Activity? How would I access it from other Activities / Fragments?

Found this code example (at the bottom of the page):

@Database(entities = [SleepNight::class], version = 1, exportSchema = false)
abstract class SleepDatabase : RoomDatabase() {

   abstract val sleepDatabaseDao: SleepDatabaseDao

   companion object {

       @Volatile
       private var INSTANCE: SleepDatabase? = null

       fun getInstance(context: Context): SleepDatabase {
           synchronized(this) {
               var instance = INSTANCE

               if (instance == null) {
                   instance = Room.databaseBuilder(
                           context.applicationContext,
                           SleepDatabase::class.java,
                           "sleep_history_database"
                   )
                           .fallbackToDestructiveMigration()
                           .build()
                   INSTANCE = instance
               }
               return instance
           }
       }
   }
}

However, I'm having a few issues with it:

  1. Why are there two instance/INSTANCE variables? I think one should suffice.

  2. The INSTANCE variable is nullable. I think the kotlin way would be a lateinit variable.

  3. syncronized(this): What is this actually in a companian object? Will it be the RoomDatabase instance? Or the caller? That would break the synchronization intent.

  4. The Dao access is a variable. The tutorial shows them as functions. Is it valid to access the Dao with a variable instead of a function?

  5. Is it a good idea to store the Room DB variable in a companion object?

On the one hand this code snippet provides a convenient solution to my introductory question. On the other hand, since I'm having so many issues with this code, I'm not sure if this is really a good idea.

Is there a generally accepted way where to put the Room DB variable? Is above code a good guide? Or should I rather follow a different approach?

1 Answers

You should be able to access your database by SleepDatabase.getInstance(context)

  1. The reason why there are two instances is that when the app is launched and no database is created the instance will be null, but when it has instantiated somewhere the value will not be null. This helps to prevent creating multiple instances of the database as the top-level INSTANCE will keep a reference of the database.

2.You can also change the nullable instance to a lateinit variable. With this, you can remove one instance and only check if the top level one is not initialised like

if (!::INSTANCE.isInitialized) {
       INSTANCE = Room.databaseBuilder(
                    context.applicationContext,
                    SleepDatabase::class.java,
                    "sleep_history_database"
                ).build()
            }
  1. This approach of creating a room database is great. Another way of creating a database would be using a DI framework or Service Locator
Related