- 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/ )
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论