getWritableDatabase与getReadableDatabase的区别

最权威莫过于官方文档和源码,下面分别以这两方面给大家看一下

文档说明

getReadableDatabase

getReadableDatabase
Added in API level 1
SQLiteDatabase getReadableDatabase ()
Create and/or open a database. This will be the same object returned by getWritableDatabase() unless some problem, such as a full disk, requires the database to be opened read-only. In that case, a read-only database object will be returned. If the problem is fixed, a future call to getWritableDatabase() may succeed, in which case the read-only database object will be closed and the read/write object will be returned in the future.
Like getWritableDatabase(), this method may take a long time to return, so you should not call it from the application main thread, including from ContentProvider.onCreate().
Returns
SQLiteDatabase a database object valid until getWritableDatabase() or close() is called.
Throws
SQLiteException if the database cannot be opened
getWritableDatabase

getReadableDatabase

SQLiteDatabase getWritableDatabase ()
Create and/or open a database that will be used for reading and writing. The first time this is called, the database will be opened and onCreate(SQLiteDatabase), onUpgrade(SQLiteDatabase, int, int) and/or onOpen(SQLiteDatabase) will be called.
Once opened successfully, the database is cached, so you can call this method every time you need to write to the database. (Make sure to call close() when you no longer need the database.) Errors such as bad permissions or a full disk may cause this method to fail, but future attempts may succeed if the problem is fixed.
Database upgrade may take a long time, you should not call this method from the application main thread, including from ContentProvider.onCreate().
Returns
SQLiteDatabase a read/write database object valid until close() is called
Throws
SQLiteException if the database cannot be opened for writing

疑问

既然getWritableDatabase与getReadableDatabase都能返回既能读又能写的Database,
为何有两个方法,岂不是累赘?况且,从方法名字来看,一个是写,一个是读,到底体现在哪里呢?

区别

getWritableDatabase取得的实例是以读写的方式打开数据库,如果打开的数据库磁盘满了,此时只能读不能写,此时调用了getWritableDatabase的实例,那么将会发生错误(异常)
getReadableDatabase取得的实例是先调用getWritableDatabase以读写的方式打开数据库,如果数据库的磁盘满了,此时返回打开失败,继而用getReadableDatabase的实例以只读的方式去打开数据库.

源码分析

 public SQLiteDatabase getWritableDatabase() {
        synchronized (this) {
            return getDatabaseLocked(true);
        }
    }
 public SQLiteDatabase getReadableDatabase() {
        synchronized (this) {
            return getDatabaseLocked(false);
        }
    }

可以看出 两者均调用了方法getDatabaseLocked(), 区别在于参数的true/false;那么getDatabaseLocked()到底是什么呢?

   public abstract class SQLiteOpenHelper {
    /**
     * 创建一个SQLite数据库的帮助类对象用于打开和管理一个数据库
     * 这个方法通常返回非常快速,这个数据库对象并不会在这里直接创建,
     * 知道调用了getWritableDatabase或者getReadableDatabase方法
     */
    public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version) {
        this(context, name, factory, version, new DefaultDatabaseErrorHandler());
    }

    /**
     * 和上面的构造函数相同,不过这里多传了一个DatabaseErrorHandler对象,
     * 这个对象用于处理数据库的异常
     */
    public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version,
            DatabaseErrorHandler errorHandler) {
        if (version < 1) throw new IllegalArgumentException("Version must be >= 1, was " + version);
        if (errorHandler == null) {
            throw new IllegalArgumentException("DatabaseErrorHandler param value can't be null.");
        }

        mContext = context;
        mName = name;
        mFactory = factory;
        mNewVersion = version;
        mErrorHandler = errorHandler;
    }


    public String getDatabaseName() {
        return mName;
    }

    /**
     * 1. 创建或打开一个可读可写的数据库,如果是第一次调用,那么数据库会被打开,oncreate,onUpgrade,open都可能调用。
     * 2. 如果打开成功,那么数据库会被缓存,所以你可以在任何时候对其进行读写。
     * 3. 如果不需要再使用这个数据库,那么确保调用close方法将其关闭。
     * 4. 如果发生错误,比如说磁盘已满,或者权限不允许,则正常调用可能会失败,修复问题后可以再次调用。
     * 5. 数据库升级可能会耗费较长时间,所以不应在应用的主线程中调用这个方法,包括ContentProvider。
     */
    public synchronized SQLiteDatabase getWritableDatabase() {
        if (mDatabase != null) {
            if (!mDatabase.isOpen()) {
                // darn! the user closed the database by calling mDatabase.close()
                mDatabase = null;
            } else if (!mDatabase.isReadOnly()) {
                return mDatabase;  // The database is already open for business
            }
        }

        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;
        if (mDatabase != null) mDatabase.lock();
        try {
            mIsInitializing = true;
            if (mName == null) {
                db = SQLiteDatabase.create(null);
            } else {
                db = mContext.openOrCreateDatabase(mName, 0, mFactory, mErrorHandler);
            }

            int version = db.getVersion();
            if (version != mNewVersion) {
                db.beginTransaction();
                try {
                    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(db);
            success = true;
            return db;
        } finally {
            mIsInitializing = false;
            if (success) {
                if (mDatabase != null) {
                    try { mDatabase.close(); } catch (Exception e) { }
                    mDatabase.unlock();
                }
                mDatabase = db;
            } else {
                if (mDatabase != null) mDatabase.unlock();
                if (db != null) db.close();
            }
        }
    }

    /**
     * 创建或者打开一个数据库,这个数据库对象和调用getWritableDatabase打开的数据库是同一个,除非发生某些意外情况,
     * 在这种情况下,一个只读的数据库对象会被返回,如果问题修复,那么下次调用getWritableDatabase将会成功
     * 这时只读的数据库会被关闭,可读可写的数据库会被返回。
     * 其他的和getWritableDatabase()方法一样。 
     */
    public synchronized SQLiteDatabase getReadableDatabase() {
        if (mDatabase != null) {
            if (!mDatabase.isOpen()) {
                // darn! the user closed the database by calling mDatabase.close()
                mDatabase = null;
            } else {
                return mDatabase;  // The database is already open for business
            }
        }

        if (mIsInitializing) {
            throw new IllegalStateException("getReadableDatabase called recursively");
        }

        try {
            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,
                    mErrorHandler);
            if (db.getVersion() != mNewVersion) {
                throw new SQLiteException("Can't upgrade read-only database from version " +
                        db.getVersion() + " to " + mNewVersion + ": " + path); /** * database. 调用已经打开的数据库,实现类在更新表之前应该检查数据库是否是只读的。 */
            }

            onOpen(db);
            Log.w(TAG, "Opened " + mName + " in read-only mode");
            mDatabase = db;
            return mDatabase;
        } finally {
            mIsInitializing = false;
            if (db != null && db != mDatabase) db.close();
        }
    }


    public synchronized void close() {
        if (mIsInitializing) throw new IllegalStateException("Closed during initialization");

        if (mDatabase != null && mDatabase.isOpen()) {
            mDatabase.close();
            mDatabase = null;
        }
    }


    public abstract void onCreate(SQLiteDatabase db);


    public abstract void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion);


    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        throw new SQLiteException("Can't downgrade database from version " +
                oldVersion + " to " + newVersion);
    }


    public void onOpen(SQLiteDatabase db) {}
}

参考

官方文档
http://blog.csdn.net/qq_29678299/article/details/51096915

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: getReadableDatabaseAndroidSQLiteOpenHelper类的一个方法,用于获取一个可读的数据库对象。该方法返回的数据库对象可以用于执行查询操作,但不能用于执行写入操作。如果需要执行写入操作,应该使用getWritableDatabase方法获取一个可写的数据库对象。 ### 回答2: getReadableDatabaseAndroidSQLite数据库的一个方法。它是SQLiteOpenHelper类的一个成员方法,用于获取一个可读的数据库对象。 在Android中,SQLite是一种轻量级的数据库引擎,广泛应用于Android应用程序的存储和管理数据。SQLiteOpenHelper是Android提供的一个帮助类,用于打开、创建和管理数据库。 getReadableDatabase方法的作用是获取一个可读的数据库对象。当调用该方法时,它会检查与给定的数据库名字相关联的数据库文件是否已创建,如果已创建,则打开该数据库文件并返回一个SQLiteDatabase对象,允许我们以只读的方式操作数据库。 返回的SQLiteDatabase对象是用于执行和管理各种数据库操作的主要接口。通过该对象,我们可以执行查询语句来获取数据库中的数据,但不能执行更新、插入或删除操作。 getReadableDatabase方法还具有自动升级数据库的功能。如果数据库版本发生变化,该方法会调用SQLiteOpenHelper中的onUpgrade方法来升级数据库版本,以便与新的数据库结构保持一致。 总之,getReadableDatabase方法是用于获取一个可读的SQLite数据库对象的方法。它可以打开已创建的数据库文件,并返回一个可读的SQLiteDatabase对象,用于查询和读取数据库中的数据。 ### 回答3: getReadableDatabaseAndroid 中的一个方法,它用于获取一个可读的 SQLite 数据库对象。这个方法主要用于访问已经存在的数据库,并且没有对数据库进行写入操作的情况下,获取一个用于查询的数据库实例。 使用 getReadableDatabase 方法可以确保我们在访问数据库时,不会触发数据库的写入操作,从而提高性能和效率。它会根据我们传入的数据库名字,在应用的默认数据库文件夹中查找并打开该数据库文件,并返回一个 SQLiteDatabase 对象。 当我们需要在应用中进行查询操作,但是又不需要写入操作时,使用 getWritableDatabase 方法就会使我们的代码显得冗余和重复。因为这个方法会在每次调用的时候都会进行数据库的写入操作,这样会浪费系统资源。 该方法返回的 SQLiteDatabase 对象可以用于执行查询操作,例如执行 SQL 语句、查询表、插入、更新、删除等操作。通过在获取到数据库对象后,我们可以通过调用 SQLiteDatabase 的 query、rawQuery、insert、update、delete 等方法来对数据库进行操作。 总之,getReadableDatabase 是一个获取可读的 SQLite 数据库对象的方法,它用于在不需要进行数据库写入操作的情况下,获取用于查询的数据库实例。这个方法能提高性能和效率,避免浪费系统资源。使用它可以方便地进行查询操作,从而满足我们对数据库的读取需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值