title: How to properly close and reopen Room Database
body: <p>Hello I have 2 apps that rely on making and restoring the backups of the app's databases just by copying the databases files in and out the sdcard and am having a hard time figuring out how to reopen the Room Database singleton after closing it to make the databases' copies.</p>
  
  <p>Building the database:</p>
  
  <pre><code>@Database(version = 15, exportSchema = true, entities = [list of entities])
  abstract class AppDatabase : RoomDatabase() {
  
  //list of DAOs
  
  companion object {
  
      @Volatile private var INSTANCE: AppDatabase? = null
  
      fun getInstance(context: Context): AppDatabase =
              INSTANCE ?: synchronized(this) {
                  INSTANCE ?: buildDatabase(context).also {
                      INSTANCE = it
                  }
              }
  
      private fun buildDatabase(context: Context) =
  
              Room.databaseBuilder(
                      context.applicationContext,
                      AppDatabase::class.java,
                      "Fazendao.sqlitedb"
              )
              .addMigrations(Migration1315)
              .build()
  
      }
  }
  </code></pre>
  
  <p>Closing the database:</p>
  
  <pre><code>fun closeDatabase() {
      if(db.isOpen) {
          db.openHelper.close()
      }
  }
  </code></pre>
  
  <p>Making the database file copy (inside a ViewModel):</p>
  
  <pre><code>fun exportaBkpObservable(nome: String, auto: String, storage: File, database: File) {
      disposable.clear()
      setFlagsNull()
  
      flagSubject.onNext(false)
  
      disposable.add(
              Observable.fromCallable {
                  repo.recordBkpName(nome)
              }
              .subscribeOn(Schedulers.io())
              .flatMap {
                  return@flatMap try {
  
                      //closing the database
                      repo.closeDatabase()
  
                      Observable.just(
                          database.copyTo(File(storage, auto), true)
                      )
                      .flatMap {
  
                          val myDb = SQLiteDatabase.openOrCreateDatabase(it, null)
                          val ok = myDb.isDatabaseIntegrityOk
  
                          if(myDb.isOpen) myDb.close()
  
                          if(ok) {
                              Observable.just(ok)
                          } else {
                              Observable.error&lt;Throwable&gt;(Throwable("CORRUPTED DATABASE"))
                          }
                      }
  
                  } catch (t: Throwable) {
                      Observable.error&lt;Throwable&gt;(t)
                  }
              }
              .subscribe(
                      {},
                      {
                          errorFlag = "exportDB: " + it.message
                          errorSubject.onNext("exportDB: " + it.message)
                      },
                      {
                          //trying to reopen database
                          repo.openDatabase()
  
                          trueFlag = true
                          flagSubject.onNext(true)
                      }
              )
      )
  
  }
  </code></pre>
  
  <p>The repo is the repository where the AppDatabase is injected, and in its turn is injected in the ViewModelFactory.</p>
  
  <p>Injection:</p>
  
  <pre><code>object MainInjection {
      private fun providesIORepo(context: Context): IORepo {
  
          return IORepo(AppDatabase.getInstance(context))
      }
  
      fun provideIOViewModelFactory(context: Context): IOViewModelFactory {
  
          val data = providesIORepo(context)
  
          return IOViewModelFactory(data)
      }
  }
  </code></pre>
  
  <p>And in the AppCompatActivity onCreate:</p>
  
  <pre><code>val modelFactory = MainInjection.provideIOViewModelFactory(this)
  viewModel = ViewModelProviders.of(this, modelFactory).get(IOViewModel::class.java)
  </code></pre>
  
  <p>Reopening the database:</p>
  
  <pre><code>fun openDatabase() {
      if(!db.isOpen){
          db.openHelper.writableDatabase
      }
  }
  </code></pre>
  
  <p>Now the error messages:</p>
  
  <p>Trying to reopen the database:</p>
  
  <pre><code>E/ROOM: Invalidation tracker is initialized twice :/.
  </code></pre>
  
  <p>And consequently the crash when I try to access it from another function:</p>
  
  <pre><code>Cannot perform this operation because the connection pool has been closed.
  </code></pre>
  
  <p>Sometimes after closing the database I have also:</p>
  
  <pre><code>E/ROOM: Cannot run invalidation tracker. Is the db closed?
  </code></pre>
  
  <p>In this post <a href="https://medium.com/google-developers/incrementally-migrate-from-sqlite-to-room-66c2f655b377" rel="noreferrer">Incrementally migrate from SQLite to Room</a> the author opens and closes the database for each access to it, so I don't understand why my implementation is not working.</p>
  
  <p>So where am I wrong ? Is there a way of deactivating the InvalidationTracker too ?</p>
  
  <p>Should I use the following code to close the database and clear the Room instance every time I have to copy the database file. Is it safe ?:</p>
  
  <pre><code>fun destroyInstance() {
  
          if (INSTANCE?.isOpen == true) {
              INSTANCE?.close()
          }
  
          INSTANCE = null
      }
  </code></pre>
  
  <p>Thanks for the attention.</p>