main

square/leakcanary

Last updated at: 29/12/2023 09:39

ScopedLeaksDb.kt

TLDR

This file contains the ScopedLeaksDb object, which provides methods for accessing a SQLite database. It manages the opening and closing of the database, and provides access to both readable and writable instances of the database.

Methods

readableDatabase

This method takes a Context parameter and a lambda function that accepts a SQLiteDatabase parameter. It opens the database in readable mode using the provided context, and passes it to the lambda function. The result of the lambda function is then returned.

writableDatabase

This method is similar to readableDatabase, but opens the database in writable mode.

open

This method takes a Context parameter and returns a DbOpener instance. It initializes the LeaksDbHelper if necessary and increments the open count.

DbOpener.close

This method is called to close the database. It checks if the database is already closed, and if not, it decrements the open count. If the open count reaches 0, it closes the database.

Classes

No classes in this file.

package leakcanary.internal.activity.db

import android.content.Context
import android.database.sqlite.SQLiteDatabase
import java.io.Closeable

internal object ScopedLeaksDb {

  @Volatile
  private lateinit var leaksDbHelper: LeaksDbHelper

  private val lock = Any()

  @Volatile
  private var openCount: Int = 0

  fun <T> readableDatabase(context: Context, block: (SQLiteDatabase) -> T): T {
    return open(context).use {
      block(it.readableDatabase)
    }
  }

  fun <T> writableDatabase(context: Context, block: (SQLiteDatabase) -> T): T {
    return open(context).use {
      block(it.writableDatabase)
    }
  }

  fun open(context: Context): DbOpener {
    synchronized(lock) {
      if (!::leaksDbHelper.isInitialized) {
        leaksDbHelper = LeaksDbHelper(context.applicationContext)
      }
      openCount++
      return DbOpener()
    }
  }

  class DbOpener : Closeable {

    private var closed = false

    val readableDatabase: SQLiteDatabase
      get() {
        checkClosed()
        return leaksDbHelper.readableDatabase
      }

    val writableDatabase: SQLiteDatabase
      get() {
        checkClosed()
        return leaksDbHelper.writableDatabase
      }

    override fun close() {
      synchronized(lock) {
        checkClosed()
        closed = true
        openCount--
        if (openCount == 0) {
          // No one else needs this right now, let's close the database (will reopen on
          // next use)
          leaksDbHelper.close()
        }
      }
    }

    private fun checkClosed() {
      check(!closed) {
        "Already closed"
      }
    }
  }
}