- CompoundButton 源码分析
- LinearLayout 源码分析
- SearchView 源码解析
- LruCache 源码解析
- ViewDragHelper 源码解析
- BottomSheets 源码解析
- Media Player 源码分析
- NavigationView 源码解析
- Service 源码解析
- Binder 源码分析
- Android 应用 Preference 相关及源码浅析 SharePreferences 篇
- ScrollView 源码解析
- Handler 源码解析
- NestedScrollView 源码解析
- SQLiteOpenHelper/SQLiteDatabase/Cursor 源码解析
- Bundle 源码解析
- LocalBroadcastManager 源码解析
- Toast 源码解析
- TextInputLayout
- LayoutInflater 和 LayoutInflaterCompat 源码解析
- TextView 源码解析
- NestedScrolling 事件机制源码解析
- ViewGroup 源码解析
- StaticLayout 源码分析
- AtomicFile 源码解析
- AtomicFile 源码解析
- Spannable 源码分析
- Notification 之 Android 5.0 实现原理
- CoordinatorLayout 源码分析
- Scroller 源码解析
- SwipeRefreshLayout 源码分析
- FloatingActionButton 源码解析
- AsyncTask 源码分析
- TabLayout 源码解析
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
SQLiteOpenHelper
封装管理数据库的创造和版本管理类
主要封装了数据库的创建和获取的方法,一般继承该类实现 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/ )
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论