getWritableDatabase与getReadableDatabase的区别

来源:互联网 发布:mac彩妆面试真的难 编辑:程序博客网 时间:2024/05/16 00:25

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

文档说明

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

0 0
原创粉丝点击