前言
- 内容很干,请结合前一篇关于Room的文章一起看
- demo地址:github.com/AfterChrist…
- 如果对你有用,请点赞收藏,感谢感谢。
DataBase注解生成的类
public final class DataBase_Impl extends DataBase {
private volatile PersonDao _personDao;
@Override
protected SupportSQLiteOpenHelper createOpenHelper(DatabaseConfiguration configuration) {
final SupportSQLiteOpenHelper.Callback _openCallback = new RoomOpenHelper(configuration, new RoomOpenHelper.Delegate(2) {
@Override
public void createAllTables(SupportSQLiteDatabase _db) {
_db.execSQL("CREATE TABLE IF NOT EXISTS `Person` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `title` TEXT NOT NULL, `type` INTEGER NOT NULL, `age` INTEGER NOT NULL)");
_db.execSQL("CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)");
_db.execSQL("INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'dc505637cc281fbab1e623c6d84bdaa5')");
}
@Override
public void dropAllTables(SupportSQLiteDatabase _db) {
_db.execSQL("DROP TABLE IF EXISTS `Person`");
if (mCallbacks != null) {
for (int _i = 0, _size = mCallbacks.size(); _i < _size; _i++) {
mCallbacks.get(_i).onDestructiveMigration(_db);
}
}
}
- 通过生成的源码可知,在生成的impl文件中创建了SupportSQLiteOpenHelper
- SupportSQLiteOpenHelper An interface to map the behavior of {**@link **android.database.sqlite.SQLiteOpenHelper}.
Dao的注解类
package com.afterchristmas.roomdemo.room;
import android.database.Cursor;
import androidx.room.EntityInsertionAdapter;
import androidx.room.RoomDatabase;
import androidx.room.RoomSQLiteQuery;
import androidx.room.util.CursorUtil;
import androidx.room.util.DBUtil;
import androidx.sqlite.db.SupportSQLiteStatement;
import java.lang.Override;
import java.lang.String;
import java.lang.SuppressWarnings;
import java.util.ArrayList;
import java.util.List;
@SuppressWarnings({"unchecked", "deprecation"})
public final class PersonDao_Impl implements PersonDao {
private final RoomDatabase __db;
private final EntityInsertionAdapter<Person> __insertionAdapterOfPerson;
public PersonDao_Impl(RoomDatabase __db) {
this.__db = __db;
this.__insertionAdapterOfPerson = new EntityInsertionAdapter<Person>(__db) {
@Override
public String createQuery() {
return "INSERT OR REPLACE INTO `Person` (`id`,`title`,`type`,`age`) VALUES (nullif(?, 0),?,?,?)";
}
@Override
public void bind(SupportSQLiteStatement stmt, Person value) {
stmt.bindLong(1, value.getCache_id());
if (value.getTitle() == null) {
stmt.bindNull(2);
} else {
stmt.bindString(2, value.getTitle());
}
stmt.bindLong(3, value.getType());
stmt.bindLong(4, value.getAge());
}
};
}
@Override
public void insert(final Person person) {
__db.assertNotSuspendingTransaction();
__db.beginTransaction();
try {
__insertionAdapterOfPerson.insert(person);
__db.setTransactionSuccessful();
} finally {
__db.endTransaction();
}
}
@Override
public List<Person> getAll() {
final String _sql = "Select * from person";
final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 0);
__db.assertNotSuspendingTransaction();
final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
try {
final int _cursorIndexOfCacheId = CursorUtil.getColumnIndexOrThrow(_cursor, "id");
final int _cursorIndexOfTitle = CursorUtil.getColumnIndexOrThrow(_cursor, "title");
final int _cursorIndexOfType = CursorUtil.getColumnIndexOrThrow(_cursor, "type");
final int _cursorIndexOfAge = CursorUtil.getColumnIndexOrThrow(_cursor, "age");
final List<Person> _result = new ArrayList<Person>(_cursor.getCount());
while(_cursor.moveToNext()) {
final Person _item;
final long _tmpCache_id;
_tmpCache_id = _cursor.getLong(_cursorIndexOfCacheId);
final String _tmpTitle;
_tmpTitle = _cursor.getString(_cursorIndexOfTitle);
final int _tmpType;
_tmpType = _cursor.getInt(_cursorIndexOfType);
final int _tmpAge;
_tmpAge = _cursor.getInt(_cursorIndexOfAge);
_item = new Person(_tmpCache_id,_tmpTitle,_tmpType,_tmpAge);
_result.add(_item);
}
return _result;
} finally {
_cursor.close();
_statement.release();
}
}
}
- 从注解类的相关的impl文件可知,dao中生成了相关的操作数据库的相关的语句
- 这一点和Sqlitehelper的操作语句一样
Room类的源码分析
首先看创建room的使用方法
Room.databaseBuilder(WanApplication.instance, DataBase::class.java, DB_NAME)
.addCallback(object : RoomDatabase.Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
Log.e("db", "create")
}
override fun onOpen(db: SupportSQLiteDatabase) {
super.onOpen(db)
Log.e("db", "open")
}
})
.allowMainThreadQueries()
.addMigrations(DataBase.MIGRATION_1_2)
.build()
RoomDatabase.Builder的作用
@NonNull
public static <T extends RoomDatabase> RoomDatabase.Builder<T> databaseBuilder(
@NonNull Context context, @NonNull Class<T> klass, @NonNull String name) {
//noinspection ConstantConditions
if (name == null || name.trim().length() == 0) {
throw new IllegalArgumentException("Cannot build a database with null or empty name."
+ " If you are trying to create an in memory database, use Room"
+ ".inMemoryDatabaseBuilder");
}
return new RoomDatabase.Builder<>(context, klass, name);
}
- 传递context参数给room类
- 传递DataBase class的类名 ** 用户反射找到注解生成impl类**
- 传递数据库的名称
- DatabaseConfiguration
- .addCallback
- .allowMainThreadQueries()
- .addMigrations(DataBase.MIGRATION_1_2)
这些东西都会添加到DatabaseConfiguration,在数据库实例init的时候会用到
build方法
/**
* Creates the databases and initializes it.
* <p>
* By default, all RoomDatabases use in memory storage for TEMP tables and enables recursive
* triggers.
*
* @return A new database instance.
*/
@SuppressLint("RestrictedApi")
@NonNull
public T build() {
//noinspection ConstantConditions
if (mContext == null) {
throw new IllegalArgumentException("Cannot provide null context for the database.");
}
//noinspection ConstantConditions
if (mDatabaseClass == null) {
throw new IllegalArgumentException("Must provide an abstract class that"
+ " extends RoomDatabase");
}
if (mQueryExecutor == null && mTransactionExecutor == null) {
mQueryExecutor = mTransactionExecutor = ArchTaskExecutor.getIOThreadExecutor();
} else if (mQueryExecutor != null && mTransactionExecutor == null) {
mTransactionExecutor = mQueryExecutor;
} else if (mQueryExecutor == null && mTransactionExecutor != null) {
mQueryExecutor = mTransactionExecutor;
}
if (mMigrationStartAndEndVersions != null && mMigrationsNotRequiredFrom != null) {
for (Integer version : mMigrationStartAndEndVersions) {
if (mMigrationsNotRequiredFrom.contains(version)) {
throw new IllegalArgumentException(
"Inconsistency detected. A Migration was supplied to "
+ "addMigration(Migration... migrations) that has a start "
+ "or end version equal to a start version supplied to "
+ "fallbackToDestructiveMigrationFrom(int... "
+ "startVersions). Start version: "
+ version);
}
}
}
if (mFactory == null) {
mFactory = new FrameworkSQLiteOpenHelperFactory();
}
if (mCopyFromAssetPath != null || mCopyFromFile != null) {
if (mName == null) {
throw new IllegalArgumentException("Cannot create from asset or file for an "
+ "in-memory database.");
}
if (mCopyFromAssetPath != null && mCopyFromFile != null) {
throw new IllegalArgumentException("Both createFromAsset() and "
+ "createFromFile() was called on this Builder but the database can "
+ "only be created using one of the two configurations.");
}
mFactory = new SQLiteCopyOpenHelperFactory(mCopyFromAssetPath, mCopyFromFile,
mFactory);
}
DatabaseConfiguration configuration =
new DatabaseConfiguration(
mContext,
mName,
mFactory,
mMigrationContainer,
mCallbacks,
mAllowMainThreadQueries,
mJournalMode.resolve(mContext),
mQueryExecutor,
mTransactionExecutor,
mMultiInstanceInvalidation,
mRequireMigration,
mAllowDestructiveMigrationOnDowngrade,
mMigrationsNotRequiredFrom,
mCopyFromAssetPath,
mCopyFromFile);
T db = Room.getGeneratedImplementation(mDatabaseClass, DB_IMPL_SUFFIX);
db.init(configuration);
return db;
}
}
- 通过Room.getGeneratedImplementation获取到注解生成的实例
- db.init()方法初始化
初始化方法分析
/**
* Called by {@link Room} when it is initialized.
*
* @param configuration The database configuration.
*/
@CallSuper
public void init(@NonNull DatabaseConfiguration configuration) {
mOpenHelper = createOpenHelper(configuration);
if (mOpenHelper instanceof SQLiteCopyOpenHelper) {
SQLiteCopyOpenHelper copyOpenHelper = (SQLiteCopyOpenHelper) mOpenHelper;
copyOpenHelper.setDatabaseConfiguration(configuration);
}
boolean wal = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
wal = configuration.journalMode == JournalMode.WRITE_AHEAD_LOGGING;
mOpenHelper.setWriteAheadLoggingEnabled(wal);
}
mCallbacks = configuration.callbacks;
mQueryExecutor = configuration.queryExecutor;
mTransactionExecutor = new TransactionExecutor(configuration.transactionExecutor);
mAllowMainThreadQueries = configuration.allowMainThreadQueries;
mWriteAheadLoggingEnabled = wal;
if (configuration.multiInstanceInvalidation) {
mInvalidationTracker.startMultiInstanceInvalidation(configuration.context,
configuration.name);
}
}
- 创建Sqliteopenhelper
- 初始化日志开关,回调,日志相关等
总结
Room的实现结构和SqliteOpenHelper类似或者基于SqliteOpenHelper,添加了相关的注解方法,简化数据库相关的书写,减少了使用的难度。