1 package leakcanary.internal.activity.db 2 3 import android.content.Context 4 import android.database.sqlite.SQLiteDatabase 5 import java.io.Closeable 6 7 internal object ScopedLeaksDb { 8 9 @Volatile 10 private lateinit var leaksDbHelper: LeaksDbHelper 11 12 private val lock = Any() 13 14 @Volatile 15 private var openCount: Int = 0 16 readableDatabasenull17 fun <T> readableDatabase(context: Context, block: (SQLiteDatabase) -> T): T { 18 return open(context).use { 19 block(it.readableDatabase) 20 } 21 } 22 writableDatabasenull23 fun <T> writableDatabase(context: Context, block: (SQLiteDatabase) -> T): T { 24 return open(context).use { 25 block(it.writableDatabase) 26 } 27 } 28 opennull29 fun open(context: Context): DbOpener { 30 synchronized(lock) { 31 if (!::leaksDbHelper.isInitialized) { 32 leaksDbHelper = LeaksDbHelper(context.applicationContext) 33 } 34 openCount++ 35 return DbOpener() 36 } 37 } 38 39 class DbOpener : Closeable { 40 41 private var closed = false 42 43 val readableDatabase: SQLiteDatabase 44 get() { 45 checkClosed() 46 return leaksDbHelper.readableDatabase 47 } 48 49 val writableDatabase: SQLiteDatabase 50 get() { 51 checkClosed() 52 return leaksDbHelper.writableDatabase 53 } 54 closenull55 override fun close() { 56 synchronized(lock) { 57 checkClosed() 58 closed = true 59 openCount-- 60 if (openCount == 0) { 61 // No one else needs this right now, let's close the database (will reopen on 62 // next use) 63 leaksDbHelper.close() 64 } 65 } 66 } 67 checkClosednull68 private fun checkClosed() { 69 check(!closed) { 70 "Already closed" 71 } 72 } 73 } 74 } 75