public synchronized SQLiteDatabase getReadableDatabase() {if (mDatabase != null && mDatabase.isOpen()) {// 如果发现mDatabase不为空并且已经打开则直接返回return mDatabase;}if (mIsInitializing) {// 如果正在初始化则抛出异常throw new IllegalStateException("getReadableDatabase called recursively");}// 开始实例化数据库mDatabasetry {// 注意这里是调用了getWritableDatabase()方法return getWritableDatabase();} catch (SQLiteException e) {if (mName == null)throw e; // Can't open a temp database read-only!Log.e(TAG, "Couldn't open " + mName + " for writing (will try read-only):", e);}// 如果无法以可读写模式打开数据库 则以只读方式打开SQLiteDatabase db = null;try {mIsInitializing = true;String path = mContext.getDatabasePath(mName).getPath();// 获取数据库路径// 以只读方式打开数据库db = SQLiteDatabase.openDatabase(path, mFactory, SQLiteDatabase.OPEN_READONLY);if (db.getVersion() != mNewVersion) {throw new SQLiteException("Can't upgrade read-only database from version " + db.getVersion() + " to "+ mNewVersion + ": " + path);}onOpen(db);Log.w(TAG, "Opened " + mName + " in read-only mode");mDatabase = db;// 为mDatabase指定新打开的数据库return mDatabase;// 返回打开的数据库} finally {mIsInitializing = false;if (db != null && db != mDatabase)db.close();}}

在getReadableDatabase()方法中,首先判断是否已存在数据库实例并且是打开状态,如果是,则直接返回该实例,否则试图获取一个可读写模式的数据库实例,如果遇到磁盘空间已满等情况获取失败的话,再以只读模式打开数据库,获取数据库实例并返回,然后为mDatabase赋值为最新打开的数据库实例。既然有可能调用到getWritableDatabase()方法,我们就要看一下了:

 public synchronized SQLiteDatabase getWritableDatabase() {if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly()) {// 如果mDatabase不为空已打开并且不是只读模式 则返回该实例return mDatabase;}if (mIsInitializing) {throw new IllegalStateException("getWritableDatabase called recursively");}// If we have a read-only database open, someone could be using it// (though they shouldn't), which would cause a lock to be held on// the file, and our attempts to open the database read-write would// fail waiting for the file lock. To prevent that, we acquire the// lock on the read-only database, which shuts out other users.boolean success = false;SQLiteDatabase db = null;// 如果mDatabase不为空则加锁 阻止其他的操作if (mDatabase != null)mDatabase.lock();try {mIsInitializing = true;if (mName == null) {db = SQLiteDatabase.create(null);} else {// 打开或创建数据库db = mContext.openOrCreateDatabase(mName, 0, mFactory);}// 获取数据库版本(如果刚创建的数据库,版本为0)int version = db.getVersion();// 比较版本(我们代码中的版本mNewVersion为1)if (version != mNewVersion) {db.beginTransaction();// 开始事务try {if (version == 0) {// 执行我们的onCreate方法onCreate(db);} else {// 如果我们应用升级了mNewVersion为2,而原版本为1则执行onUpgrade方法onUpgrade(db, version, mNewVersion);}db.setVersion(mNewVersion);// 设置最新版本db.setTransactionSuccessful();// 设置事务成功} finally {db.endTransaction();// 结束事务}}onOpen(db);success = true;return db;// 返回可读写模式的数据库实例} finally {mIsInitializing = false;if (success) {// 打开成功if (mDatabase != null) {// 如果mDatabase有值则先关闭try {mDatabase.close();} catch (Exception e) {}mDatabase.unlock();// 解锁}mDatabase = db;// 赋值给mDatabase} else {// 打开失败的情况:解锁、关闭if (mDatabase != null)mDatabase.unlock();if (db != null)db.close();}}}

大家可以看到,几个关键步骤是,首先判断mDatabase如果不为空已打开并不是只读模式则直接返回,否则如果mDatabase不为空则加锁,然后开始打开或创建数据库,比较版本,根据版本号来调用相应的方法,为数据库设置新版本号,最后释放旧的不为空的mDatabase并解锁,把新打开的数据库实例赋予mDatabase,并返回最新实例。

看完上面的过程之后,大家或许就清楚了许多,如果不是在遇到磁盘空间已满等情况,getReadableDatabase()一般都会返回和getWritableDatabase()一样的数据库实例,所以我们在DBManager构造方法中使用getWritableDatabase()获取整个应用所使用的数据库实例是可行的。当然如果你真的担心这种情况会发生,那么你可以先用getWritableDatabase()获取数据实例,如果遇到异常,再试图用getReadableDatabase()获取实例,当然这个时候你获取的实例只能读不能写了。

原文:

http://blog.csdn.net/liuhe688/article/details/6715983/

实例代码:

http://download.csdn.net/detail/u011109881/9427744

getReadableDatabase VS getWritableDatabase相关推荐

  1. getReadableDatabase与getWritableDatabase的区别

    在Android中,通过getReadableDatabase与getWritableDatabase()都可以获得一个可以对数据库进行操作的实例.然后都可以对数据库进行增.删.查.改.,但是两者也存 ...

  2. getReadableDatabase() 和 getWritableDatabase()的区别

    2019独角兽企业重金招聘Python工程师标准>>> Android使用getWritableDatabase()和getReadableDatabase()方法都可以获取一个用于 ...

  3. Android getReadableDatabase() 和 getWritableDatabase()

    Android使用getWritableDatabase()和getReadableDatabase()方法都可以获取一个用于操作数据库的SQLiteDatabase实例.(getReadableDa ...

  4. Android存储方式之SQLite

    前言 SQLite数据库操作在Android开发中非常常用 今天我将带大家全面了解关于SQLite数据库的操作(增.删.查.改) 目录 1. SQLite数据库介绍 SQLite是Android内置的 ...

  5. SQLite数据库操作

    安卓中创建数据库的步骤: 1.写一个类MyOpenHelper继承SQLiteOpenHelper类 2.覆写其中的OnCreate(SQLiteDatabase db)和onUpgrade(SQLi ...

  6. 附带数据库的应用程序

    如果您的应用程序需要一个数据库,并且它带有内置数据,那么最好的运输方法是什么? 我是不是该: 预先创建SQLite数据库并将其包含在.apk ? 在应用程序中包括SQL命令,并让它创建数据库并在首次使 ...

  7. SQLite实例分析

    一. SQLite介绍  SQLite是android内置的一个很小的关系型数据库.  SQLite的官网是http://www.sqlite.org/,可以去下载一些文档或相关信息.  博客中有一篇 ...

  8. Android数据存储的三种方式-SharedPrefrences,File,SQLite

    1,使用SharedPrefrences 用于简单少量的数据,数据的格式简单:都是普通的字符串,标量类型的值等,比如各种配置信息等等 SharedPrefrences与Editor简介: 创建Shar ...

  9. Android学习--持久化(三) SQLite LitePal

    SQLite & LitePal 自己做为一个iOS开发,看到安卓这一块的时候,那中浓烈的熟悉味道更加强烈,SQLite这种轻量级的关系型数据库的使用在移动端相差不多,iOS有FMDB,And ...

最新文章

  1. 软件中的易用性设计及测试(三)之实践
  2. 安装clangd:‘GLIBC_2.18‘ not found解决
  3. Linux局域网搭建
  4. TLD(Tracking-Learning-Detection)学习与源码理解之(三)
  5. java 线程一直运行状态_详解JAVA 线程-线程的状态有哪些?它是如何工作的?
  6. Java中基础数据类型分类
  7. EntityFramework和EntityFramework.Extended使用说明——性能,语法和产生的sql
  8. drools 决策表_骆驼和春天的Drools决策表
  9. php进程间通信 yoc_续上篇Swoole多进程数据共享的问题
  10. 关于HTTPS的简要内容
  11. W3Cschoool菜鸟教程
  12. Pr视频剪辑软件使用小结
  13. 凭借这份diao炸天的资料,狂刷三遍成功从外包进入了字节跳动!
  14. FSA-Net学习笔记
  15. 一场 Chat 拥有自己的博客
  16. Jenkins项目实战之-MacOS High Sierra自动化打包方案的填坑之旅
  17. 舆情指数在哪里可以查到?具体平台与工具参考
  18. DWH和DB以及DATA Mart区别
  19. K近邻(KNN)详解
  20. pfam基本介绍,以及蛋白质序列下载

热门文章

  1. Golang 受欢迎的原因:大道至简
  2. HDOJ2013_蟠桃记
  3. 求数组所有区间最大值减去最小值之差的和(贝壳笔试题)
  4. 简单混合锁(HybridLock)
  5. js模板引擎 之handlebars.js
  6. 有规律的进行效果最好--打扫有感
  7. jQuery 根据值或者文本选中select
  8. Junk-Mail Filter_并查集(hdu 2473)
  9. linux crontab 怎么用,Linux crontab 如何使用
  10. oopc——2.类与对象