返回介绍

SQLiteOpenHelper

发布于 2024-12-23 21:41:49 字数 4283 浏览 0 评论 0 收藏 0

封装管理数据库的创造和版本管理类

主要封装了数据库的创建和获取的方法,一般继承该类实现 onCreate()、onUpdate() 方法,在 onCreate 创建数据库,在 onUpdate 进行数据库升级操作。其中还有 onConfigure()、onDowngrade()、onOpen() 方法,将会在下面获取数据库对象分析进行解析

数据库的获取: 两个方法:getReadableDatabase()、getWritableDatabase()。需要注意的一点是这两个方法都加锁,是线程安全的。这两个方法最终调用 getDatabaseLocked(boolean writable):

private SQLiteDatabase getDatabaseLocked(boolean writable) {
  if (mDatabase != null) {
    
    if (!mDatabase.isOpen()) {  // 判断数据库是否已经关闭
      // Darn!  The user closed the database by calling mDatabase.close().
      mDatabase = null;
    } else if (!writable || !mDatabase.isReadOnly()) { //判断数据库是否符合要求,如果数据库可读可写则返回,即!mDatabase.isReadOnly() 一直为 true
      // The database is already open for business.
      return mDatabase;
    }
  }

  // 正在初始化中
  if (mIsInitializing) {
    throw new IllegalStateException("getDatabase called recursively");
  }

  SQLiteDatabase db = mDatabase;
  try {
    mIsInitializing = true;

    if (db != null) { // 数据库不为 null,需要重新开启读写数据库使得符合要求
      if (writable && db.isReadOnly()) {
        db.reopenReadWrite();
      }
    } else if (mName == null) {
      db = SQLiteDatabase.create(null);
    } else {
      try {
        if (DEBUG_STRICT_READONLY && !writable) {
          final String path = mContext.getDatabasePath(mName).getPath();
          db = SQLiteDatabase.openDatabase(path, mFactory,
              SQLiteDatabase.OPEN_READONLY, mErrorHandler);
        } else {
          // 通过 mContext.openOrCreateDatabase 创建数据库,其实还是调用 SQLiteDatabase.openDatabase(..) 创建数据库
          db = mContext.openOrCreateDatabase(mName, mEnableWriteAheadLogging ?
              Context.MODE_ENABLE_WRITE_AHEAD_LOGGING : 0,
              mFactory, mErrorHandler);
        }
      } catch (SQLiteException ex) {
        if (writable) {
          throw ex;
        }
        Log.e(TAG, "Couldn't open " + mName
            + " for writing (will try read-only):", ex);
        final String path = mContext.getDatabasePath(mName).getPath();
        db = SQLiteDatabase.openDatabase(path, mFactory,
            SQLiteDatabase.OPEN_READONLY, mErrorHandler);
      }
    }

    // 调用 onConfigure
    onConfigure(db);

    final int version = db.getVersion();
    if (version != mNewVersion) {
      if (db.isReadOnly()) {
        throw new SQLiteException("Can't upgrade read-only database from version " +
            db.getVersion() + " to " + mNewVersion + ": " + mName);
      }

      db.beginTransaction();
      try {
        // 当第一次创建数据库时 DataBase 的版本为 0,会调用 onCreate() 方法
        if (version == 0) {
          onCreate(db);
        } else {  // 判断数据库版本升降级,调用相应方法
          if (version > mNewVersion) {
            onDowngrade(db, version, mNewVersion);
          } else {
            onUpgrade(db, version, mNewVersion);
          }
        }
        db.setVersion(mNewVersion);
        db.setTransactionSuccessful();
      } finally {
        db.endTransaction();
      }
    }

    // 调用 onOpen() 方法
    onOpen(db);

    if (db.isReadOnly()) {
      Log.w(TAG, "Opened " + mName + " in read-only mode");
    }

    mDatabase = db;
    return db;
  } finally {
    mIsInitializing = false;
    // 数据库创建失败时,进行 close 操作
    if (db != null && db != mDatabase) {
      db.close();
    }
  }
}

onCreate()、onUpdate()、onConfigure()、onDowngrade()、onOpen() 方法的调用规则:

  • onConfigure(): 当第一次调用 getReadableDatabase() 或者 getWritableDatabase() 会调用 onConfigure(),如果第一是获取到只读形式的数据库,当转换成可写形式数据库时会再次调用 onConfigure()。
  • onCreate() mDatabase 第一次创建时会调用 onCreate()
  • onUpdate() / onDowngrade() 在版本改变时会调用相应的 onUpdate() 或 onDowngrade() 方法,
  • onConfigure() 至于 onOpen() 的调用规则同 onConfigure()。

那么 onConfigure() 和 onOpen() 方法可以干嘛呢,从 api 文档可以看到:

  • 可以在 onConfigure 开启 SQLite 的 WAL 模式 ,以及 设置外键的支持
  • 而 onOpen() 方法是说明数据库已经打开,可以进行一些自己的操作,但是 需要通过 SQLiteDatabase#isReadOnly 方法检查数据库是否真正打开了
  • 开启 WAL 方法:setWriteAheadLoggingEnabled(boolean enabled) WAL 支持读写并发,是通过将修改的数据单独写到一个 wal 文件中,默认在到达一个 checkpoint 时会将数据合并入主数据库中 至于关于 WAL 的详细介绍和分析可以参见 SQLite3 性能深入分析]( http://blog.xcodev.com/posts/sqlite3-performance-indeep/ )

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文