一、SQLite源碼解析
(1)SQLiteOpenHelper源碼
public SQLiteOpenHelper(@Nullable Context context, @Nullable String name,
@Nullable CursorFactory factory, int version) {
this(context, name, factory, version, null);
}
public SQLiteOpenHelper(@Nullable Context context, @Nullable String name,
@Nullable CursorFactory factory, int version,
@Nullable DatabaseErrorHandler errorHandler) {
this(context, name, factory, version, 0, errorHandler);
}
public SQLiteOpenHelper(@Nullable Context context, @Nullable String name,
@Nullable CursorFactory factory, int version,
int minimumSupportedVersion, @Nullable DatabaseErrorHandler errorHandler) {
this(context, name, version, minimumSupportedVersion,
new SQLiteDatabase.OpenParams.Builder());
mOpenParamsBuilder.setCursorFactory(factory);
mOpenParamsBuilder.setErrorHandler(errorHandler);
}
private SQLiteOpenHelper(@Nullable Context context, @Nullable String name, int version,
int minimumSupportedVersion,
@NonNull SQLiteDatabase.OpenParams.Builder openParamsBuilder) {
Preconditions.checkNotNull(openParamsBuilder);
if (version < 1) throw new IllegalArgumentException("Version must be >= 1, was " + version);
mContext = context;
mName = name;
mNewVersion = version;
mMinimumSupportedVersion = Math.max(0, minimumSupportedVersion);
setOpenParamsBuilder(openParamsBuilder);
}
(2)SQLiteOpenHelper.getWritableDatabase與getReadableDatabase源碼
//獲得一個可讀寫的數(shù)據(jù)庫
public SQLiteDatabase getWritableDatabase() {
synchronized (this) {
return getDatabaseLocked(true);
}
}
//獲得一個只讀的數(shù)據(jù)庫
public SQLiteDatabase getReadableDatabase() {
synchronized (this) {
return getDatabaseLocked(false);
}
}
private SQLiteDatabase getDatabaseLocked(boolean writable) {
if (mDatabase != null) {
if (!mDatabase.isOpen()) {
//如果數(shù)據(jù)庫已經(jīng)關閉,需要重新打開
mDatabase = null;
} else if (!writable || !mDatabase.isReadOnly()) {
//數(shù)據(jù)庫沒有關閉,直接返回
return mDatabase;
}
}
SQLiteDatabase db = mDatabase;
try {
mIsInitializing = true;
if (db != null) {
if (writable && db.isReadOnly()) {
//當前數(shù)據(jù)是只讀狀態(tài),需要獲取可寫的數(shù)據(jù)庫
db.reopenReadWrite();
}
} else if (mName == null) {
//數(shù)據(jù)庫名稱為null,為Memory Db
db = SQLiteDatabase.createInMemory(mOpenParamsBuilder.build());
} else {
//獲取數(shù)據(jù)庫保存路徑
final File filePath = mContext.getDatabasePath(mName);
//數(shù)據(jù)庫創(chuàng)建的相關配置項
SQLiteDatabase.OpenParams params = mOpenParamsBuilder.build();
try {
//創(chuàng)建數(shù)據(jù)庫操作SQLiteDatabase實例
db = SQLiteDatabase.openDatabase(filePath, params);
setFilePermissionsForDb(filePath.getPath());
} catch (SQLException ex) {
if (writable) {
throw ex;
}
params = params.toBuilder().addOpenFlags(SQLiteDatabase.OPEN_READONLY).build();
db = SQLiteDatabase.openDatabase(filePath, params);
}
}
//創(chuàng)建數(shù)據(jù)庫成功,回調(diào)此方法配置數(shù)據(jù)庫
onConfigure(db);
//獲取當前數(shù)據(jù)庫版本,默認為0
final int version = db.getVersion();
//mNewVersion是自行設置的版本號
if (version != mNewVersion) {
//此時如果是只讀狀態(tài),將無法對數(shù)據(jù)庫做任何更改
if (db.isReadOnly()) {
throw new SQLiteException("Can't upgrade read-only database from version " +
db.getVersion() + " to " + mNewVersion + ": " + mName);
}
//如果當前版本號小于最小支持的版本,刪除數(shù)據(jù)庫
if (version > 0 && version < mMinimumSupportedVersion) {
File databaseFile = new File(db.getPath());
onBeforeDelete(db);
db.close();
//刪除數(shù)據(jù)庫文件
if (SQLiteDatabase.deleteDatabase(databaseFile)) {
mIsInitializing = false;
//刪除成功重新創(chuàng)建數(shù)據(jù)庫
return getDatabaseLocked(writable);
} else {
throw new IllegalStateException("Unable to delete obsolete database "
+ mName + " with version " + version);
}
} else {
//開啟事務
db.beginTransaction();
try {
//數(shù)據(jù)庫第一次創(chuàng)建回調(diào)執(zhí)行onCreate
if (version == 0) {
onCreate(db);
} else {
if (version > mNewVersion) {
//降級回調(diào)
onDowngrade(db, version, mNewVersion);
} else {
//升級回調(diào)
onUpgrade(db, version, mNewVersion);
}
}
//設置當前最后版本
db.setVersion(mNewVersion);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
}
//表示數(shù)據(jù)庫已經(jīng)打開回調(diào)
onOpen(db);
//賦值給當前成員
mDatabase = db;
return db;
} finally {
mIsInitializing = false;
if (db != null && db != mDatabase) {
db.close();
}
}
}
//獲取自定義或默認路徑
@Override
public File getDatabasePath(String name) {
File dir;
File f;
if (name.charAt(0) == File.separatorChar) {
//自定義存儲路徑
String dirPath = name.substring(0, name.lastIndexOf(File.separatorChar));
dir = new File(dirPath);
name = name.substring(name.lastIndexOf(File.separatorChar));
f = new File(dir, name);
if (!dir.isDirectory() && dir.mkdir()) {
FileUtils.setPermissions(dir.getPath(),
FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
-1, -1);
}
} else {
//默認路徑
dir = getDatabasesDir();
f = makeFilename(dir, name);
}
return f;
}
public static final class OpenParams {
//保存當前數(shù)據(jù)庫相關配置
private OpenParams(int openFlags, CursorFactory cursorFactory,
DatabaseErrorHandler errorHandler, int lookasideSlotSize, int lookasideSlotCount,
long idleConnectionTimeout, String journalMode, String syncMode) {
//打開模式
mOpenFlags = openFlags;
//Cursor工廠
mCursorFactory = cursorFactory;
mErrorHandler = errorHandler;
mLookasideSlotSize = lookasideSlotSize;
mLookasideSlotCount = lookasideSlotCount;
//空閑連接超時時間
mIdleConnectionTimeout = idleConnectionTimeout;
//日志模式
mJournalMode = journalMode;
//同步模式
mSyncMode = syncMode;
}
}
SQLiteOpenHelper主要完成SQLiteDatabase 的創(chuàng)建、關閉、升/降級、配置等相關輔助管理
(3)SQLiteDatabase.openDatabase獲取SQLiteDatabase實例源碼
public static SQLiteDatabase openDatabase(@NonNull File path,
@NonNull OpenParams openParams) {
return openDatabase(path.getPath(), openParams);
}
private static SQLiteDatabase openDatabase(@NonNull String path,
@NonNull OpenParams openParams) {
Preconditions.checkArgument(openParams != null, "OpenParams cannot be null");
//創(chuàng)建SQLiteDatabase實例,將OpenParams配置參數(shù)傳入SQLiteDatabase
SQLiteDatabase db = new SQLiteDatabase(path, openParams.mOpenFlags,
openParams.mCursorFactory, openParams.mErrorHandler,
openParams.mLookasideSlotSize, openParams.mLookasideSlotCount,
openParams.mIdleConnectionTimeout, openParams.mJournalMode, openParams.mSyncMode);
//調(diào)用SQLiteDatabase的open
db.open();
return db;
}
//將前面保存相關創(chuàng)建配置的 OpenParams 信息保存到 SQLiteDatabaseConfiguartion 中
private SQLiteDatabase(final String path, final int openFlags,
CursorFactory cursorFactory, DatabaseErrorHandler errorHandler,
int lookasideSlotSize, int lookasideSlotCount, long idleConnectionTimeoutMs,
String journalMode, String syncMode) {
mCursorFactory = cursorFactory;
mErrorHandler = errorHandler != null ? errorHandler : new DefaultDatabaseErrorHandler();
//SQLiteDatabase的創(chuàng)建模式,主要影響數(shù)據(jù)庫連接池打開模式
mConfigurationLocked = new SQLiteDatabaseConfiguration(path, openFlags);
mConfigurationLocked.lookasideSlotSize = lookasideSlotSize;
mConfigurationLocked.lookasideSlotCount = lookasideSlotCount;
//禁用低內(nèi)存設備上的lookaside分配器
if (ActivityManager.isLowRamDeviceStatic()) {
mConfigurationLocked.lookasideSlotCount = 0;
mConfigurationLocked.lookasideSlotSize = 0;
}
long effectiveTimeoutMs = Long.MAX_VALUE;
// Never close idle connections for in-memory databases
if (!mConfigurationLocked.isInMemoryDb()) {
//空閑連接超時,默認值-1表示未設置值
if (idleConnectionTimeoutMs >= 0) {
effectiveTimeoutMs = idleConnectionTimeoutMs;
} else if (DEBUG_CLOSE_IDLE_CONNECTIONS) {
//默認為false,表示空閑連接不會被關閉
effectiveTimeoutMs = SQLiteGlobal.getIdleConnectionTimeout();
}
}
mConfigurationLocked.idleConnectionTimeoutMs = effectiveTimeoutMs;
mConfigurationLocked.journalMode = journalMode;
mConfigurationLocked.syncMode = syncMode;
if (!SQLiteGlobal.isCompatibilityWalSupported() || (
SQLiteCompatibilityWalFlags.areFlagsSet() && !SQLiteCompatibilityWalFlags
.isCompatibilityWalSupported())) {
//不支持兼容性WAL,則禁用掉兼容性WAL
mConfigurationLocked.openFlags |= DISABLE_COMPATIBILITY_WAL;
}
}
private void open() {
try {
try {
openInner();
} catch (SQLiteDatabaseCorruptException ex) {
onCorruption();
openInner();
}
} catch (SQLiteException ex) {
close();
throw ex;
}
}
//創(chuàng)建當前SQLiteDatabase的數(shù)據(jù)庫連接池SQLiteConnectionPool
private void openInner() {
synchronized (mLock) {
assert mConnectionPoolLocked == null;
//打開數(shù)據(jù)庫連接池,ConfigurationLocked作為參數(shù)
mConnectionPoolLocked = SQLiteConnectionPool.open(mConfigurationLocked);
mCloseGuardLocked.open("close");
}
synchronized (sActiveDatabases) {
//緩存當前SQLiteDatabase實例
sActiveDatabases.put(this, null);
}
}
(4)SQLiteConnectionPool.open源碼
public static SQLiteConnectionPool open(SQLiteDatabaseConfiguration configuration) {
if (configuration == null) {
throw new IllegalArgumentException("configuration must not be null.");
}
//創(chuàng)建數(shù)據(jù)庫連接池
SQLiteConnectionPool pool = new SQLiteConnectionPool(configuration);
//調(diào)用open可能拋出異常
pool.open();
return pool;
}
private SQLiteConnectionPool(SQLiteDatabaseConfiguration configuration) {
mConfiguration = new SQLiteDatabaseConfiguration(configuration);
//設置連接池的大小
setMaxConnectionPoolSizeLocked();
//在Long.MAX_VALUE下永遠不會關閉連接
if (mConfiguration.idleConnectionTimeoutMs != Long.MAX_VALUE) {
//超時管理的Handler
setupIdleConnectionHandler(Looper.getMainLooper(),
mConfiguration.idleConnectionTimeoutMs);
}
}
private void setMaxConnectionPoolSizeLocked() {
if (!mConfiguration.isInMemoryDb()
&& (mConfiguration.openFlags & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0) {
mMaxConnectionPoolSize = SQLiteGlobal.getWALConnectionPoolSize();
} else {
mMaxConnectionPoolSize = 1;
}
}
//SQLiteGlobal.java
public static int getWALConnectionPoolSize() {
int value = SystemProperties.getInt("debug.sqlite.wal.poolsize",
Resources.getSystem().getInteger(
com.android.internal.R.integer.db_connection_pool_size));
//連接池默認最小為2,最大取決于系統(tǒng)配置
return Math.max(2, value);
}
@VisibleForTesting
public void setupIdleConnectionHandler(Looper looper, long timeoutMs) {
synchronized (mLock) {
//創(chuàng)建IdleConnectionHandler,超時管理的Handler
mIdleConnectionHandler = new IdleConnectionHandler(looper, timeoutMs);
}
}
private class IdleConnectionHandler extends Handler {
//保存配置的空閑連接超時時間
private final long mTimeout;
IdleConnectionHandler(Looper looper, long timeout) {
super(looper);
mTimeout = timeout;
}
@Override
public void handleMessage(Message msg) {
// Skip the (obsolete) message if the handler has changed
synchronized (mLock) {
if (this != mIdleConnectionHandler) {
return;
}
//關閉空閑超時的SQLiteConnection
if (closeAvailableConnectionLocked(msg.what)) {
}
}
}
void connectionReleased(SQLiteConnection con) {
//根據(jù)連接id,發(fā)送超時消息
sendEmptyMessageDelayed(con.getConnectionId(), mTimeout);
}
void connectionAcquired(SQLiteConnection con) {
removeMessages(con.getConnectionId());
}
void connectionClosed(SQLiteConnection con) {
//移除當前超時機制,說明連接被重新使用
removeMessages(con.getConnectionId());
}
}
private void open() {
//創(chuàng)建數(shù)據(jù)庫主鏈接,只有主連接才可以寫數(shù)據(jù)庫,每一個數(shù)據(jù)庫連接池默認僅有一條主連接
mAvailablePrimaryConnection = openConnectionLocked(mConfiguration,
true /*primaryConnection*/);
synchronized (mLock) {
if (mIdleConnectionHandler != null) {
//由于此時還沒有任何使用,故開啟空閑超時關閉機制
mIdleConnectionHandler.connectionReleased(mAvailablePrimaryConnection);
}
}
mIsOpen = true;
mCloseGuard.open("close");
}
private SQLiteConnection openConnectionLocked(SQLiteDatabaseConfiguration configuration,
boolean primaryConnection) {
//當前連接的唯一id
final int connectionId = mNextConnectionId++;
//創(chuàng)建連接
return SQLiteConnection.open(this, configuration,
connectionId, primaryConnection); // might throw
}
//從連接池獲取到一個 SQLiteConnection
public SQLiteConnection acquireConnection(String sql, int connectionFlags,
CancellationSignal cancellationSignal) {
//獲取一個SQLiteConnection
SQLiteConnection con = waitForConnection(sql, connectionFlags, cancellationSignal);
synchronized (mLock) {
if (mIdleConnectionHandler != null) {
//移除該連接的超時關閉消息
mIdleConnectionHandler.connectionAcquired(con);
}
}
return con;
}
//對該連接開啟超時關閉機制
public void releaseConnection(SQLiteConnection connection) {
synchronized (mLock) {
if (mIdleConnectionHandler != null) {
//重新加入超時關閉機制
mIdleConnectionHandler.connectionReleased(connection);
}
//code...
}
}
(5)SQLiteConnection.open源碼
static SQLiteConnection open(SQLiteConnectionPool pool,
SQLiteDatabaseConfiguration configuration,
int connectionId, boolean primaryConnection) {
//創(chuàng)建SQLiteConnection,每個SQLiteConnection對一個native層一個操作句柄
SQLiteConnection connection = new SQLiteConnection(pool, configuration,
connectionId, primaryConnection);
try {
//調(diào)用自己的open方法
connection.open();
return connection;
} catch (SQLiteException ex) {
connection.dispose(false);
throw ex;
}
}
private SQLiteConnection(SQLiteConnectionPool pool,
SQLiteDatabaseConfiguration configuration,
int connectionId, boolean primaryConnection) {
//持有數(shù)據(jù)庫連接池
mPool = pool;
//操作日志
mRecentOperations = new OperationLog(mPool);
//持有數(shù)據(jù)庫配置信息
mConfiguration = new SQLiteDatabaseConfiguration(configuration);
//該鏈接的唯一id
mConnectionId = connectionId;
//是否是主鏈接
mIsPrimaryConnection = primaryConnection;
//是否是只讀模式
mIsReadOnlyConnection = (configuration.openFlags & SQLiteDatabase.OPEN_READONLY) != 0;
//緩存預編譯后的SQL語句,內(nèi)部采用LRU算法
mPreparedStatementCache = new PreparedStatementCache(
mConfiguration.maxSqlCacheSize);
mCloseGuard.open("close");
}
private void open() {
//創(chuàng)建數(shù)據(jù)庫操作句柄
mConnectionPtr = nativeOpen(mConfiguration.path, mConfiguration.openFlags,
mConfiguration.label,
SQLiteDebug.DEBUG_SQL_STATEMENTS, SQLiteDebug.DEBUG_SQL_TIME,
mConfiguration.lookasideSlotSize, mConfiguration.lookasideSlotCount);
//設置頁緩存大小
setPageSize();
setForeignKeyModeFromConfiguration();
//根據(jù)Configuration設置WAL模式
setWalModeFromConfiguration();
setJournalSizeLimit();
setAutoCheckpointInterval();
setLocaleFromConfiguration();
// Register custom functions.
final int functionCount = mConfiguration.customFunctions.size();
for (int i = 0; i < functionCount; i++) {
SQLiteCustomFunction function = mConfiguration.customFunctions.get(i);
nativeRegisterCustomFunction(mConnectionPtr, function);
}
}