前言
下面的解析也是总体到细节去一步步剥离当前demo为主线涉及的Room源码部分。
demo
demo路径在AAC-core-demo下(下载当前github上的源码是记得是Room tag标签)。
我们应该运行一下当前demo,知道它是干什么的
-
在输入框输入随意信息,e.g. 啦啦啦;
-
点击按钮
UPDATE USERENAME,当前输入框会更新如图所示的输入框上方; -
关闭当前app,再次打开上次输入的信息(e.g.啦啦啦)被保留并展示在如图所示的输入框上方。
出现这种情况的原因:我们使用了androidx源码中的room组件。通过room操作supportSqlite,supportSqlite再去操作android源码中的sqlite组件。
- 知道是Room插件即可,这里的supportSqlite就是androidx源码中sqlite组件的具体实现几个类,前缀都是supportSQLite。
总体到细节
下面开始一步步深入细节的去理解当前Room源码。
-
app模块:demo模块,使用Room;
-
room模块:设计到的子模块不只是上面的两个,room-runtime和room-compiler,我们暂主要理解这两个即可;
-
(1) room-runtime:被demo引用的依赖,通过当前模块去操作数据库,相当于把数据库的操作分为两部分:一部分自己处理,一部分交给androidx中sqlite模块去处理;
-
(2) room-compiler:用于根据demo中的注解,为demo生成类(这里不做研究,后面会有专门的文章去分析,以及room注解的用法);
-
(3)补:还有room-rxjava2:当前为了room兼容使用rxjava2;
- sqlite模块:两个子模块,一个子模块还叫sqlite,一个子模块是sqlite-framework;
- (1)sqlite:定义supportSqlite各个类,类方法实际还是沿用android源码中的sqlite组件中的方法;room组件中使用的是该sqlite子模块的类
- (2)sqlite-framework:①实现sqlite子模块接口,所以room组件中使用的虽然是sqlite子模块类,但是实际还是sqlite-framework中的实现类;②当前类通过代理方式实现android源码中的sqlite组件方法;③生成android源码中的sqlite组件的类作为framework类的代理;
下面针对每个模块,有外向内一步步讲解:
app模块
描述写的越多越乱,第一是个人水平问题;第二,是确实不易写的那么全,看起来乱的很。我感觉这样挺清晰的。
如果所示,这里采用的是MVVM模式,下面对当前框架进行简单讲解,较简单:
-
Activity从ViewModel获取数据,ViewModel从UserDataSource中获取数据;
-
Injection(使用了注解思想,理解注解应该非常容易理解这种实现方式)类启到衔接作用:
- (1)提供ViewModelFactory生成ViewModel实例;
- (2)为生成ViewModel实例提供构造函数参数UserDataSource,实际给的是UserDataSource的子类LocalUserDataSource;
- (3)实例化UserDatabase,将UserDataBase中的userDao作为LocalUserDataSource类构造函数参数;
-
所以VieModel中操作的UserDataSource实际是LocalUserDataSource类;
-
UserDataBase类的操作我们作为Room模块讲解,这里可以当做暗箱来理解。
room模块
当前demo为主线解说room源码,我们分为两步骤来解说:(1)room初始化工作;(2)room操作数据库操作:①插入或更新数据库,②查询;
涉及到room注解部分(如xxx_Impl类)会单独有一章介绍room注解的具体使用;sqlite部分(SupportSQLite的实例化)下面sqlite模块部分会做讲解。
room初始化
如上图所示,room初始化的重要作用有两个:
-
返回的UsersDatabase实例对象是UsersDatabase_Impl;
-
新建了FrameworkSQLiteOpenHelperFactory对象,当前对象的作用是创建FrameworkSQLiteOpenHelper类;
简单讲解下上图流程:
-
app模块调用UserDatabase类的getInstance()方法实例化;
-
UsersDatabase继承RoomDatabase类,RoomDatabase是通过Builder构造者模式构建的,所以这里调用的是RoomDatabase的build()方法; build()方法做了3件事情:
-
(1)实例化很多参数,这里比较重要的是
mQueryExecutor = mTransactionExecutor线程池和factory = new FrameworkSQLiteOpenHelperFactory,将实例化后的参数传递给DatabaseConfiguration(字面意思:存储数据库配置信息); -
(2)调用Room的getGeneratedImplementation()方法,根据注解命名规则实例化UsersDatabase_impl类,该类继承UsersDatabase(UsersDatabase继承RoomDatabase类);
-
(3)调用RoomDatabase的init()方法,该方法调用createOpenHelper()抽象方法,具体实现在UsersDatabase_Impl类中;
- UsersDatabase_Impl类的createOpenHelper()方法返回SupportSQLiteOpenHelper接口对象,这里通过DatabaseConfiguration类中的factory参数
factory = new FrameworkSQLiteOpenHelperFactory调用create()方法创建FrameworkSQLiteOpenHelper对象作为实际返回对象;
- createOpenHelper()方法中的RoomOpenHelper等等,先别急着看,用到了再说,很多虽然存在,但是不一定用到了。
room操作数据库
如上图,实际操作数据库部分并不难,但是需要注意的是这里操作数据库的几个类:SupportSQLiteStatement和SupportSQLiteDatabase实际实例对象分别是FrameworkSQLiteStatement和FrameworkSQLiteDatabase,并且这里操作数据库都是通过RoomDatabase中的SupportSQLiteOpenHelper mOpenHelper来控制。
疑问:CREATE TABLE IF NOT EXISTS users在哪???
答:存在于UsersDatabase_Impl的createOpenHelper()方法中了,如下图
至于如何调用关下,请听下面sqlite模块的讲解。
sqlite模块
前一章说了Sqlite模块,但是说的一头雾水,看的也是一脸懵逼。这里可以相对来说较详细对它进一步理解了。
- 在RoomDatabase中统一管理
SupportSQLiteOpenHelper mOpenHelper:
- (1)需要操作数据库必须使用mOpenHelper参数;
- (2)操作数据库必须调用RoomDatabase中的mOpenHelper参数;
-
SupportSQLiteOpenHelper mOpenHelper实例化在UserDatabase_Impl类的createOpenHelper()方法中; -
执行FrameworkSqLiteOpenHelper的方法,实际执行的是getDelegate()代理中的方法,代理返回的是OpenHelper对象,OpenHelper对象继承SQLiteOpenHelper类,由此可知Sqlite的核心是理解FrameworkSQLiteOpenHelper类中的OpenHelper类;
-
查看OpenHelper类:
-
(1)查看getSupportDatabase()方法,返回的是SupportSQLiteDatabase接口对象,该方法:①调用innerGetDatabase()方法,如果
Sample.db文件不存在则创建;并且获取读或写权限SQLiteDatabase对象;②将获取读或写权限SQLiteDatabase对象作为FrameworkSQLiteDatabase类构造函数参数,对FrameworkSQLiteDatabase实例化。所以实际返回的是FrameworkSQLiteDatabase类,并且该类的所有方法操作的是用读或写权限SQLiteDatabase代理对象的方法; -
(2)onCreate()方法,调用SupportSQLiteOpenHelper接口内部类Callback的onCreate()方法,①该Callback抽象类在UserDatabase_Impl类的createOpenHelper()方法中被实现RoomOpenHelper类;②RoomOpenHelper类的onCreate方法调用Delegate抽象类的createAllTables()方法,也就是回答了上面
CREATE TABLE IF NOT EXISTS users在哪???的问题
总结
个人感觉解说的还行。其实源码我来回看了很多遍,细节部分都没有放弃,写这篇文章很有必要,能够把零散的东西通过这篇文章整合成一个有架构感的设计思想。