本系列将从无到有一步步解析Room源码。解析过程中,我们始终不要记住,Room其实是对Sqlite的增删改查。只不过加了自己的很多思想去润色。
解析顺序,本系列将根据以下系列解说Room源码架构:
涉及最基础的Sqlite增删改查(Room使用到的增删改查)和对Sqlite的封装(Androidx的Sqlite架构)
当前demo为主线涉及到的Room源码主线部分解说;
Room compiler代码生成部分源码解说,以及对Room注解根据源码写一个使用文档;
如果对SQLite的应用不了解,没办法对Room进行解析。

SQLitDatabase家族部分成员,相关类的说明如下(除了下面以外,没做解释的可以不用看,和Room没啥多大关系):
SQLiteOpenHelper是一个帮助(Utility)类,用于方便开发者创建和管理数据库。
SQLiteDatabase代表SQLite数据库,它内部封装了一个Native层的sqlite3实例。
SQLiteStatement用于描述和SQL语句相关的信息。
SQLiteProgram是基类,它提供了一些API用于参数绑定。
SQLiteQuery主要用于query查询操作,而SQLiteStatement用于query之外的一些操作(根据SDK的说明,如果SQLiteStatement用于query查询,其返回的结果集只能是1行*1列)。
当前数据库存在demo.db数据库文件中,一个用户表users:userid和username两个字段,userid表示主键。实现如下:
创建数据库文件,并获取SQLiteDatabase数据库对象:
public class OpenHelper extends SQLiteOpenHelper{
final Context mContext;
public OpenHelper(Context context, String name,int version){
super(context,name,null,version);
mContext = context;
}
public SQLiteDatabase getSQLiteDatabase(boolean writele){
String name = getDatabaseName();
if (name != null) {
//数据库文件如果不存在,那么新建
File databaseFile = mContext.getDatabasePath(name);
File parentFile = databaseFile.getParentFile();
if (parentFile != null) {
parentFile.mkdirs();
if (!parentFile.isDirectory()) {
Log.w(TAG, "Invalid database parent file, not a directory: " + parentFile);
}
}
}
try {
return getWritableOrReadableDatabase(writable);
} catch (Throwable t) {
// No good, just try again...
super.close();
}
return null;
}
public SQLiteDatabase getWritableOrReadableDatabase(boolean writable) {
if (writable) {
return super.getWritableDatabase();
} else {
return super.getReadableDatabase();
}
}
}
//实例化OpenHelper,并且操作SQLiteDatabase都是在该类中通过getWritableOrReadableDatabase(writable)获取读写权限
OpenHelper openHelper = new OpenHelper(context,“demo.db”,1);
添加和修改SQLite数据库 - 插入先开启事务,事务提示成功,最后结束事务:
private void insert(User user){
SQLiteDatabase sqliteDatabase = openHelper.getSupportDatabase(true);
sqliteDatabase.beginTransaction();
try {
insertUser(sqliteDatabase,user);
sqliteDatabase.setTransactionSuccessful();
return null;
} finally {
sqliteDatabase.endTransaction();
}
}
private void insertUser(SQLiteDatabase sqliteDatabase,User user){
String query = "INSERT OR REPLACE INTO `users` (`userid`,`username`) VALUES (?,?)";
//compileStatement方法为了SQLiteStatement可重复利用
SQLiteStatement sqliteStatement = sqliteDatabase.compileStatement(query);
bind( stmt, value);
stmt.executeInsert();
}
private void bind(SQLiteStatement stmt, User value) {
if (value.getId() == null) {
stmt.bindNull(1);
} else {
stmt.bindString(1, value.getId());
}
if (value.getUserName() == null) {
stmt.bindNull(2);
} else {
stmt.bindString(2, value.getUserName());
}
}
删除SQLite,这个是删除表,删除某个字段应该也比较简单,修改query = "delete from users where userid = xxx"即可
private void deleteUserTable(SQLiteStatement stmt){
String query = "DELETE FROM Users";
//compileStatement方法为了SQLiteStatement可重复利用
SQLiteStatement sqliteStatement = sqliteDatabase.compileStatement(query);
SQLiteDatabase sqliteDatabase = openHelper.getSupportDatabase(true);
sqliteDatabase.beginTransaction();
try {
stmt.executeUpdateDelete();
sqliteDatabase.setTransactionSuccessful();
} finally {
sqliteDatabase.endTransaction();
}
}
查询SQLite
public User getUser(SQLiteDatabase sqliteDatabase){
final String sql = “SELECT * FROM Users LIMIT 1”;
final Cursor cursor =sqliteDatabase.rawQuery(sql,null);
try {
final int cursorIndexOfMId = CursorUtil.getColumnIndexOrThrow(cursor, "userid");
final int cursorIndexOfMUserName = CursorUtil.getColumnIndexOrThrow(cursor, "username");
final User result;
if(cursor.moveToFirst()) {
final String _tmpMId;
if (cursor.isNull(cursorIndexOfMId)) {
tmpMId = null;
} else {
tmpMId = cursor.getString(cursorIndexOfMId);
}
final String tmpMUserName;
if (cursor.isNull(cursorIndexOfMUserName)) {
tmpMUserName = null;
} else {
tmpMUserName = cursor.getString(cursorIndexOfMUserName);
}
result = new User(tmpMId,tmpMUserName);
} else {
result = null;
}
return result;
} finally {
cursor.close();
}
}
代码是从源码你们抠出来的,理解起来也应该非常简单,这里理解对后面的源码理解有好处。
sqlite源码我只针对sqlite和sqlite-framework进行讲解:这两部分代码量也非常小,虽然简单,但对后面Room的理解至关重要。
该模块主要启到规范使用SQLite的作用,当前操作SupportSQLite替代SQLite,省去其他SQLite中不必要的一些方法。
Callback抽象类:传入当前操作的数据库版本,用于对数据库的创建、打开、升级、降级、文件损坏处理;
Configuration类:创建sqliteOpenHelper类时的参数这里配置;
Builder类:使用构建者模式实例化Configuration类;
Factory接口:创建当前SupportSQLiteOpenHelper实例,传递Configuration类提供参数;
SupportSQLiteDatabase接口:数据库操作方法,这里的方法和SQLiteDatabase基本一致;
SupportSQLiteProgram接口:数据库字段绑定,根据字段类型,选取绑定类型,例如bindLong(int index,long value),表示当前绑定的字段是long类型,参数index表示当前字段处于数据库表中的位置;
SupportSQLiteQuery接口:数据库query工作;
SupportSQLiteStatement接口:规范数据库增删改查执行方法;
SupportSQLiteCompat类:SQLiteDatabase兼容性处理;
SimpleSQLiteQuery类:当前类继承SupportSQLiteQuery接口,存取sqlite的query和根据输入字段数组,确定SupportSQLiteProgram接口中的绑定类型;
SupportSQLiteQueryBuilder类:构建者模式新建一个SimpleSQLiteQuery类,该类用于查询表中字段信息,可以实现精确查询。
以上说的非常非常抽象,可以按照SQLite去理解。不比过于纠结,我们继续看sqlite-framework(也是一个比较抽象的模块)
当前模块比较重要的特点:1. 继承sqlite模块下的接口;2. 采用代理模式执行代理方法;
FrameworkSQLiteOpenHelperFactory类:工厂模式创建FrameworkSQLiteOpenHelper类;
FrameworkSQLiteDatabase类:该类传递一个SQLiteDatabase数据库类作为代理对象delegate,继承SupportSQLiteDatabase接口,实现该接口的所有操作数据库方法,这些方法其实还是操作代理delegate的方法;
FrameworkSQLiteProgram类:构造函数传递SQLiteProgram对象作为delegate代理,继承SupportSQLiteProgram接口,该接口实现方法实际操作的是delegate代理的相应方法;
FrameworkSQLiteStatement类:继承FrameworkSQLiteProgram类,用于精确执行sql;构造函数传递SQLiteStatement delegate代理对象,该类继承SupportSQLiteStatement接口执行的实现方法最终执行的还是delegate代理的相应方法;
FrameworkSQLiteOpenHelper类:该类只管重要
怎么说了感觉和没说一个样!!!我在哪?我是谁???我在干啥!!!
当前模块同样的比较抽象。可以从FrameworkSQLiteOpenHelper类的getDelegate方法为切入点去摸索,看个大概,我们继续往下才能明白人家具体含义。
代码还得仔细看下,因为后面room实际操作的就是sqlite-framework中的各个实现类,入口当然是FrameworkSQLiteOpenHelperFactory,新建一个操作FrameworkSQLiteDatabase类的FrameworkSQLiteOpenHelper类。
在思考一个问题,sqlite和sqlite-framework有必要吗?我直接使用SQlite不是更好,为什么要使用这里的SupportSqlite:通过一系列代理,实际执行的还是SQLite。